Solved

Number of cells in array  in C/C++

Posted on 2013-11-04
23
492 Views
Last Modified: 2013-11-04
Dear Experts,

I just tried one simple example of C/C++ program on 64-bit Linux in which just
want to find out of number of cells in one array.
But I get different result from main() and fn() function. Why ?
Could you help this ?

As I know, one double is 8-byte and my array cells are 5 so
sizeof(array) should be  40 . So the result,5, from main() is correct
but the result from fn() is 1 , Why ?

40/8-->5 in main() but 8/8-->1 in fn(), Why ?

Is it * str_numbers in fn() incorrect declaration ?

Please advise
Duncan




#include <stdio.h>
#include<float.h>
int fn(double  * str_numbers)
{
    int total = sizeof(str_numbers)/sizeof(str_numbers[0]);
//    printf("In f: %d\n", total);
    printf("size of whole:%d\n",sizeof(str_numbers));  
    printf("size of one cell:%d\n",sizeof(str_numbers[0]));
    return total;
}

int main ()
{
    double  str_numbers[5] = {23000.678,23010.22,23800.345,22320.12,20345.456};
    int total = sizeof(str_numbers)/sizeof(str_numbers[0]);
    printf("size of whole:%d\n",sizeof(str_numbers));
    printf("size of one cell:%d\n",sizeof(str_numbers[0]));
    printf ("No of  cell In main: %d\n", total);

printf("%s\n","===========================================");

printf("No of cell in fn:%d\n",    fn(str_numbers));
    return 0;
}

Open in new window

0
Comment
Question by:duncanb7
  • 11
  • 8
  • 4
23 Comments
 
LVL 45

Expert Comment

by:Kdo
ID: 39621406
Hi duncan,

All that's passed to fn is the address of the array.  You can pass double*, double[], double[1000], etc from the calling function, but there's nothing in the address (or the passed object) that indicates the number of items in the array.  All that's passed is the address..


Good Luck,
Kent
0
 
LVL 13

Author Comment

by:duncanb7
ID: 39621416
int fn(double  str_numbers)
{

}

I tried it without * pointer but gave me the complier error, Why ?
0
 
LVL 45

Expert Comment

by:Kdo
ID: 39621430
Parameters are passed by the C putting something on the stack.  (The stack is just a place in memory used to pass parameters and put the temporary variables used by the function.)  In your last example, function fn expects a double to be passed to it.  A single variable.  When the parameter is defined as a double*, the address of the variable will be passed.  When you think about passing a single variable, the difference is pretty subtle.  But when you think about passing an array it makes more sense.  You wouldn't want to put the entire array on the stack as the array could literally hold millions of items that would have to be copied to the stack and then back to the calling program.  Passing the address allows the function to access exactly the elements of the array that it needs.

When you pass a single item, you can pass by address or by value (by using the * or not), but the function must also be coded with the correct syntax to match how the variable is passed.


Kent
0
 
LVL 13

Author Comment

by:duncanb7
ID: 39621483
So how can I pass the array from str_number into the function that do the same
thing as in main ();
0
 
LVL 13

Author Comment

by:duncanb7
ID: 39621494
int fn(double  str_numbers[])
{

}

there is no complier error but the result of fn() is still 1 not 5, Why ?
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 39621505
Hi duncanb7,

as Kdo mentioned above regardless whether you pass a 'double*' or a 'double[]' just a pointer to the first element of the array is passed to the function so within the function there's no chance to determine the size of the array.

So the only way to achieve what you want is to add an additional parameter to pass the size, i.e.:
int fn(double  * str_numbers, int total)
{
    printf("size of whole:%d\n",sizeof(double)*total);  
    printf("size of one cell:%d\n",sizeof(str_numbers[0]));
    return total;
}

int main ()
{
    double  str_numbers[5] = {23000.678,23010.22,23800.345,22320.12,20345.456};
    int total = sizeof(str_numbers)/sizeof(str_numbers[0]);
    printf("size of whole:%d\n",sizeof(str_numbers));
    printf("size of one cell:%d\n",sizeof(str_numbers[0]));
    printf ("No of  cell In main: %d\n", total);

printf("%s\n","===========================================");

printf("No of cell in fn:%d\n",    fn(str_numbers,total));
    return 0;
}

ZOPPO
0
 
LVL 45

Assisted Solution

by:Kdo
Kdo earned 250 total points
ID: 39621510
As noted above, all that is passed is the starting address of the array.  There is no mechanism in C to pass an address and have the called function know anything more than the address, and by implication, the nature of the structure defined in the function header.  Length simply isn't passed.

You can "simulate" it with your own structure, but that's not the same thing.

typedef struct ArrayDescriptorDouble
{
  double *Address;
  int Size;
} ADD_t;

Then populate those two items and pass it (or it's address) to the function.  But passing a double* or double[], or double[100] passes only the starting address.  There is no guarantee or even implication of the length of the array.


Kent
0
 
LVL 13

Author Comment

by:duncanb7
ID: 39621540
dear zoppo,

Please review my thread question. I want to know why
the result is different between the code at main() and fn() even
the coding is same beside pass array into function.

The target I want to the number of array cells can be found in function fn()
instead of main();


Why such simple task can cost a lot of time ?
0
 
LVL 45

Expert Comment

by:Kdo
ID: 39621572
Hi Duncan,

The short answer is because the called function doesn't know the size of the array.  The C convention is that because the called function doesn't know, 1 is assumed.  Both Zoppo and I have been trying to explain why that is instead of giving a 1 sentence answer that amounts to "because that's the way it is".


Kent
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 39621584
Ok, maybe you should first think about the sizeof operator. You can read something about it (including samples similar to your problem here) i.e. at http://en.wikipedia.org/wiki/Sizeof

There you'll fine in most cases, sizeof is a compile-time operator, and that's exacly what's the cause for the difference between instantiating an array like
  double a[] = { 1.0, 2.0, 3.0 };
  int s = sizeof( a ); // will be 3*sizeof(double)
and passing an array like
  void fn( double a[] )
  {
   int s = sizeof( a ); // will be sizeof( double* )

This is because only in the first case the compiler can determine the size of the array at compile time, for the second case there's no way to determine the size of the array, neither ar compile time nor at runtime.

ZOPPO
0
 
LVL 13

Author Comment

by:duncanb7
ID: 39621601
<link deleted because it violates site guidelines for off site content COBOLdinosaur, Topic Advisor>

Arrays decay to pointers in function calls. It's not possible to compute the size of an array which is only represented as a pointer in any way, including using sizeof.

So it is impossible to pass array into function for sizeof , I found a lot in google there
are a lot people experienced the same issue  but not solved and just do sizeof and pass
result of sizeof into function

In other words, can't sizeof array in function ,
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 45

Expert Comment

by:Kdo
ID: 39621616
>> In other words, can't sizeof array in function

You CAN use sizeof() within a function.  It returns the size of the object passed.  What is passed is the address of the array and sizeof() dutifully returns 1, the number of addresses passed.
0
 
LVL 13

Author Comment

by:duncanb7
ID: 39621630
yes it can sizeof() in function but with the result we not expect so
we refer can't sizeof () in function if array is passed into it

Anyway, any other methods, we can
get the number of cells in array in function  () when array is passed into function(0 ?
0
 
LVL 13

Author Comment

by:duncanb7
ID: 39621638
Any now I know why like PHP and node.js at server-side more than C/C++
0
 
LVL 45

Expert Comment

by:Kdo
ID: 39621641
No.  If it's critical that the function knows the number of items in the array, you'll need to pass that as a separate parameter or use something like the structure container that I showed above.


Kent
0
 
LVL 13

Author Comment

by:duncanb7
ID: 39621648
I tried yours but the result is same as before, Could you send me you complete code
for us ?

#include <stdio.h>
#include<float.h>
typedef struct ArrayDescriptorDouble
{
  double *Address;
  int Size;
} ADD_t;
int fn(double   str_numbers[])
{
    int total = sizeof(str_numbers)/sizeof(str_numbers[0]);
//    printf("In f: %d\n", total);
    printf("size of whole:%d\n",sizeof(str_numbers));  
    printf("size of one cell:%d\n",sizeof(str_numbers[0]));
    return total;
}

int main ()
{
    double  str_numbers[5] = {23000.678,23010.22,23800.345,22320.12,20345.456};
    int total = sizeof(str_numbers)/sizeof(str_numbers[0]);
    printf("size of whole:%d\n",sizeof(str_numbers));
    printf("size of one cell:%d\n",sizeof(str_numbers[0]));
    printf ("No of  cell In main: %d\n", total);

printf("%s\n","===========================================");

printf("No of cell in fn:%d\n",    fn(str_numbers));
    return 0;
}

Open in new window

0
 
LVL 30

Accepted Solution

by:
Zoppo earned 250 total points
ID: 39621664
Well, if you get more familiar with C/C++ you'll see sizeof in a function leads to expected results too ;o)

BTW, to avoid confusion I would suggest to avoid [] in function declarations, it is absoluteley the same as passing a pointer like in void fn ( double* a );.

And: You can't really compare C/C++ with PHP or Javascript. These are scripting languages with dynamic type system which internally use a lot of functionality to hide such details form the user, in C/C++ the user has to implement such things on a quite low-level base.

To do it like Kdo suggested you need to even use the declared structure, i.e.:
typedef struct ArrayDescriptorDouble
{
  double *Address;
  int Size;
} ADD_t;

int fn(ADD_t* pData)
{
    int total = pData->Size;
    printf("size of whole:%d\n",total);  
    return total;
}

int main ()
{
    double  str_numbers[5] = {23000.678,23010.22,23800.345,22320.12,20345.456};
    int total = sizeof(str_numbers)/sizeof(str_numbers[0]);
    printf("size of whole:%d\n",sizeof(str_numbers));
    printf("size of one cell:%d\n",sizeof(str_numbers[0]));
    printf ("No of  cell In main: %d\n", total);

    printf("%s\n","===========================================");

    ADD_t data;
    data.Address = str_numbers;
    data.Size = sizeof(str_numbers)/sizeof(str_numbers[0]);
    printf("No of cell in fn:%d\n",    fn( &data ));
    return 0;
}

ZOPPO
0
 
LVL 45

Expert Comment

by:Kdo
ID: 39621668
Adding a structure definition doesn't really help unless you use it in the program.  :)

In this case, you probably just want to modify the function *fn* and pass the length.

#include <stdio.h>
#include<float.h>
 
int fn(double   str_numbers[], int size)
{
    int total = size * sizeof(str_numbers[0]);

    printf("In f: %d\n", total);
    printf("size of whole:%d\n", size);  
    printf("size of one cell:%d\n",sizeof(str_numbers[0]));
    return total;
}

int main ()
{
    double  str_numbers[5] = {23000.678,23010.22,23800.345,22320.12,20345.456};
//    int total = sizeof(str_numbers)/sizeof(str_numbers[0]);
    printf("size of whole:%d\n",sizeof(str_numbers));
    printf("size of one cell:%d\n",sizeof(str_numbers[0]));
    printf ("No of  cell In main: %d\n", total);

printf("%s\n","===========================================");

printf("No of cell in fn:%d\n", fn (str_numbers, sizeof (str_numbers)));
return 0;
}

Open in new window

0
 
LVL 13

Author Comment

by:duncanb7
ID: 39621692
dear zoppo,

your code is working and result are all 5  and only one array arg pass into fn()
that is what I want. I don't want to pass two argv into function() as Kda did but
his idea suggestion also help to finish this thread.

Last question, since I am not really fimilar with C,
when I complier the following code, that will give me
warning such as
10:warning:incompatible implict declaration of bulit-in function "printf" in
18:warning:incompatible implict declaration of bulit-in function "printf" in

COuld I avoid this warning ?


typedef struct ArrayDescriptorDouble
{
  double *Address;
  int Size;
} ADD_t;

int fn(ADD_t* pData)
{
    int total = pData->Size;
    printf("size of whole:%d\n",total);  
    return total;
}

int main ()
{
    double  str_numbers[5] = {23000.678,23010.22,23800.345,22320.12,20345.456};
    int total = sizeof(str_numbers)/sizeof(str_numbers[0]);
    printf("size of whole:%d\n",sizeof(str_numbers));
    printf("size of one cell:%d\n",sizeof(str_numbers[0]));
    printf ("No of  cell In main: %d\n", total);

    printf("%s\n","===========================================");

    ADD_t data;
    data.Address = str_numbers;
    data.Size = sizeof(str_numbers)/sizeof(str_numbers[0]);
    printf("No of cell in fn:%d\n",    fn( &data ));
    return 0;
}

Open in new window

0
 
LVL 13

Author Closing Comment

by:duncanb7
ID: 39621701
Thanks for your suggestion and final solution

If possible, please also answer the warning issue after complier zoppo's code

Duncan
0
 
LVL 45

Expert Comment

by:Kdo
ID: 39621714
Make sure that the program includes:

#include <stdio.h>

at the top of the source code.


Kent
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 39621725
Hm - I guess a type-or signed/unsigned mismatch warning could occur at
  > data.Size = sizeof(str_numbers)/sizeof(str_numbers[0]);
since ADD_t::Size is of type int (which most probably is a 32-bit signed type) while sizeof returns a size_t (in your case I guess it's an unsinged, 64-bit type).

So you should change ADD_t to look like this:

typedef struct ArrayDescriptorDouble
{
  double *Address;
  size_t Size;
} ADD_t;

If this doesn't help please post the exact warning ...

ZOPPO
0
 
LVL 13

Author Comment

by:duncanb7
ID: 39621760
Thanks Kdo,

after add back stdio.h the warning is gone.

This thread is trying practise more C  code before making decision on
replacing  some huge some mathematical PHP code by C/C++ or
node.js on my server.

C and node.js in speed is much faster than PHP ,and PHP and Javascript code(node.js) is
much easier to use than C/C++.

Anyway, this might be next topic

Hava a nice day
Duncan
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Linux users are sometimes dumbfounded by the severe lack of documentation on a topic. Sometimes, the documentation is copious, but other times, you end up with some obscure "it varies depending on your distribution" over and over when searching for …
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now