The count is returning unpredictable results. Sometimes they are right. Sometimes totally weird. Anyone can tell me what is wrong?
#include <stdio.h>
int len(int[]);
int main (int argc, const char * argv[])
{
int a[]={1,2,3,4,5,6,7,8};
int* i = a;
printf("length is %d",(len(i)));
return 0;
}
int len(int* a){
int count = 0;
for (; *a!='\0'; a++) {
count++;
}
return count;
}
There is not going to be a zero at the end of your array unless you put one there! A literal char array defined using a character string does, indeed, have such a sentinel value, but they're special; other arrays have no equivalent.
The len() function you're trying to write cannot be written for general arrays in C -- there's no way to determine the size of a dynamic array without using the (undocumented, platform-specific) internals of the memory allocator. If it was important to do this for your application, you could only do it if it were possible for you to add a zero at the end of every array yourself, explicitly.
I think you're confused between C strings (arrays of char) and other arrays. It's a convention that C strings are terminated with a null character ('\0'), but not all arrays (even char arrays) are terminated this way.
The general convention is to either store the length of an array somewhere, or to use a sentinel value at the end of the array. This value should be one that won't come up inside the array - eg '\0' in strings, or -1 in an array of positive ints.
Also, if you know that a is an int array (and not a pointer to an int array), then you can use:
size_t length = sizeof(a) / sizeof(a[0]);
So you could do:
int a[] = {1,2,3,4,5,6,7,8};
size_t length = sizeof(a) / sizeof(a[0]);
// In this case, sizeof(a[0])
// is the same as sizeof(int), because it's an int array.
But you can't do:
int *a = malloc(sizeof(int) * 10);
size_t length = sizeof(a) / sizeof(a[0]); // WRONG!
That last example will compile, but the answer will be wrong, because you're getting the size of a pointer to the array rather than the size of the array.
Note that you also can't use this sizeof to read the size of an array that's been passed into a function. It doesn't matter whether you declare your function len(int *a) or len(int a[]) - a will be a pointer, because the compiler converts arrays in function arguments to be a pointer to their first element.
You cannot count arrays like that. Only strings are null terminated. If you want that to work reliably, you will need to add an additional element to your array that contains '\0'. But be sure to remember to take into account that your length will no be one larger then the true length because of that '\0'
Unlike strings, normal arrays do not terminate with a null byte 0x00. The reason strings use this is because arrays have no concept of length; arrays are merely contiguous pieces of memory, it is up to you to keep track of the length of arrays.
Related
I’m taking a C class on Udemy. Unfortunately the instructor isn’t replying to my question so I thought I’d try this site. My assumption is that it is probably fairly common when developing a program to not know how many elements may be part of an array. When initializing an array the instructor recommends not specifying a size but to let the compiler do it.
Example: int array[ ] = {2,3,4,5,6,7,8};
Obviously, using this method there is no index to use to terminate looping. According to “C Primer Plus” by Stephen Prata the element after the last element in the array is a valid pointer location:
(pg. 406) - C guarantees that when it allocates space for an array, a
pointer to the first location after the end of the array is a valid
pointer.
If I’m using pointer notation (array++) to loop through the array, what condition can I use to terminate the looping? Is there a value in that location after the final element that I can use? Is that value always the same or does it change depending on the type of array?
In C pointers are signed. That has consequences dealing with array-like data structures where you might:
while (a <= a+last) {
...
a++;
}
if the index one beyond the end of a could have a change of sign, then that code could fail. Idiomatic C does not suggest the above; but it needs to be preserved, thus this limitation.
In system code, it is possible that you deal with allocations that do not conform to this, thus you should try to work with the idiomatic:
while (a < a+len) {
...
a++
}
So, for your exact question:
for (size_t i = 0; i < sizeof array/sizeof array[0]; i++) {
...
}
or
for (int *p = array; p < array + sizeof array / sizeof array[0]; p++) {
...
}
Your basic idea (looping through an array using pointers) is sound; however, there are a number of points in your question that need some attention.
Is there a value in that location after the final element that I can use? Is that value always the same or does it change depending on the type of array?
Yes, there is a (almost certainly) some value in that location, but it's not something you can ever use! The pointer to the 'one-past-the-end' element is valid only for use in pointer arithmetic or comparison operations; attempting to dereference it (to read the value at that address) is undefined behaviour.
You can get that 'one-past-the-end' pointer by adding the number of elements in the array to the address of the array's first element (or the array 'name' itself). The idiomatic way to get the number of elements in an array is to divide the size of the entire array by the size of its first element. So, for your array, we can declare and initialize our "end pointer" like this, using the sizeof operator:
int* end = array + sizeof(array) / sizeof(*array);
// int* end = array + sizeof array / sizeof *array; // Alternative form: "()" optional
Another important point: In your question you mention using array++ to loop through your array variable. You cannot do this, because array isn't actually a (modifiable) pointer variable – it's the name of a variable (an array) whose location is fixed at the point when main (or whatever function it is declared inside) is entered. Instead, you will need to copy the address of the array into another int* pointer, and increment that in the loop.
With those points in mind, here's an illustrative example of how you can loop through your array using a pointer:
#include <stdio.h>
int main(void)
{
int array[] = { 2,3,4,5,6,7,8 };
int* end = array + sizeof(array) / sizeof(*array);
for (int* p = array; p < end; ++p) {
// Note that, when we reach p == end, the loop will not run, so ...
printf("%d\n", *p); // ...we never attempt the *p operation on that
}
return 0;
}
A couple of other points of clarification:
The int* p = array assignment works (and is perfectly valid C) because an array variable name can readily decay into a pointer to its first element (as it will if you pass that array as an argument to a function, for example). See: What is array to pointer decay?
Because of that last point above, you cannot use the sizeof(a)/sizeof(*a) paradigm to determine the size of an array in a function it is passed to as an argument; in such cases, you need to pass the array's size as an additional argument. See: How do I determine the size of my array in C?
This question already has answers here:
How can I get the size of an array from a pointer in C?
(16 answers)
Closed 1 year ago.
I have a pointer to an array in C which I would like to iterate through, but I don't know the size:
int *array;
I am unsure as to how I should proceed. I was thinking that I should probably try by finding the size by doing:
int array_size = sizeof(array) / sizeof(int);
But I don't know if that could work. I was wondering if there was a more optimal way of doing this?
In C, there is no way to tell the number of elements in an array from a pointer to an element. sizeof(array) / sizeof(*array) only works for an actual array, not for a pointer, which is what a function receives as an argument, even if the array syntax is used in the function prototype. In this case sizeof(array) evaluates to the size of the pointer, so dividing that by the size of an element is meaningless.
The best approach for your function to get the number of elements is to provide it as a separate argument.
If this is not practical, there are different ways to infer the number of elements, relying on a convention that must be adhered to by the callers:
the array could have a known fixed number of elements
the array could have a sentinel value as the last element of the array.
It is common to use a null pointer (NULL) as such a sentinel for arrays of pointers, such as the char *argv[] argument of the main() function, but note that int argc is also provided to this function.
The null byte (\0) is used to tell the end of C strings, which are arrays of char.
In your case, you could consider 0 or -1 to signify the end of the array, but this convention must be used consistently by all callers of your function.
You cannot iterate over an array in c without knowking the number of elements.
Please note that sizeof(array) / sizeof(array[0]) won't work on a pointer, i.e it will not give the number of elements in the array.
It will also not work inside a function, where the array was passed as an argument due to array decay to pointer.
If the array does not contain a known sentinel value (as for example character arrays that contain strings have as the sentinel value the terminating zero character '\0') then you can not find its end.
If you have a pointer like this
int *array;
then the expression sizeof( array ) will yield the size of the pointer itself that does not depend on whether the pointer points to a single object of the type int or to the first element of an integer array with a known number of elements in the array. That size for example can be equal either to 4 or 8 depending on the used system. Thus the expression sizeof( array ) / sizeof( int ) in general will always yield either 1 or 2.
So you have to pass to the function explicitly also the number of elements in the array.
You could determine the number of elements in an array if you pass a pointer to the whole array. For example
void f( int( *a )[10] );
//...
int a[10];
//...
f( &a );
In this case dereferencing the pointer within the function you will get an object of the array type. Thus the expression sizeof( *a ) will yield the size of the original array.
I have a pointer to an array in c to which I would like to iterate through but I don't know the size:
You are in luck if you truly have a pointer to an array as the type of a pointer to an array carries information about the array size.
int some_array[7] = {1, 2, 3, 4, 5, 6, 7};
int (*pointer_to_an_array)[7] = &some_array;
#define N (sizeof(*pointer_to_an_array) / sizeof(*pointer_to_an_array[0]))
for (size_t i = 0; i < N; i++) {
printf("%d\n", (*pointer_to_an_array)[i]);
}
Unfortunately, with int *array;, code does not have a pointer to an array, but a pointer to an int and information about the original array size of some_array[] is not available through array.
int some_array[7] = {1,2,3,4,5,6,7};
int *array = some_array; // Not a pointer to an array
Carry information about array size in another variable.
size_t some_array_n = sizeof some_array/ sizeof some_array[0];
I am trying to create a function to copy an array into another using pointers. I'd like to add the following condition : if the array of destination is smaller, the loop must break.
So basically it's working, but it is not working if I intilize the the destination array as follows :
int dest_array[10] = {0};
From what I understand it fills the array with int 0's which are equivalent to '\0' (null characters). So here is my question :
In this case how can the computer know the array size or when it ends ?
(And how do I compare arrays passed as parameters ?)
void copy(int *src_arr, int *dest_arr)
{
// The advantage of using pointers is that you don't need to provide the source array's size
// I can't use sizeof to compare the sizes of the arrays because it does not work on parameters.
// It returns the size of the pointer to the array and not of of the whole array
int* ptr1;
int* ptr2;
for( ptr1 = source, ptr2 = dest_arr ;
*ptr1 != '\0' ;
ptr1++, ptr2++ )
{
if(!*ptr2) // Problem here if dest_arr full of 0's
{
printf("Copy interrupted :\n" +
"Destination array is too small");
break;
}
*ptr2 = *ptr1;
}
In C, it is impossible to know the length of an array inherently. This is due to the fact that an array is really just a contiguous chunk of memory, and the value passed to functions is really just a pointer to the first element in the array. As a result of this, to actually know the length of an array within a function other than the function where that array was declared, you have to somehow provide that value to the function. Two common approaches are the use of sentinel values which indicate the last element (similar to the way '\0', the null character, is per convention interpreted as the first character not part of a string in C), or providing another parameter which contains the array length.
As a very common example of this: if you have written any programs which use command-line parameters, then surely you are familiar with the common definition of int main(int argc, char *argv[]), which uses the second of the aforementioned approaches by providing the length of the argv array via the argc parameter.
The compiler has some ways to work around this for local variables. E.g., the following would work:
#include <stdio.h>
int main(){
int nums[10] = {0};
printf("%zu\n", sizeof(nums)/sizeof(nums[0]));
return 0;
}
Which prints 10 to STDOUT; however, this only works because the sizeof operation is done locally, and the compiler knows the length of the array at that point.
On the other hand, we can consider the situation of passing the array to another function:
#include <stdio.h>
int tryToGetSizeOf(int arr[]){
printf("%zu", sizeof(arr)/sizeof(arr[0]));
}
int main(){
int nums[10] = {0};
printf("%zu\n", sizeof(nums)/sizeof(nums[0]));
puts("Calling other function...");
tryToGetSizeOf(nums);
return 0;
}
This will end up printing the following to STDOUT:
10
Calling other function...
2
This may not be the value you're expecting, but this occurs due to the fact that the method signature int tryToGetSizeOf(int arr[]) is functionally equivalent to int tryToGetSizeOf(int *arr). Therefore, you are dividing the size of an integer pointer (int *) by the size of a single int; whereas while you're still in the local context of main() (i.e., where the array was defined originally), you are dividing the size of the allocated memory region by the size of the datatype that memory region is partitioned as (int).
An example of this available on Ideone.
int* ptr1;
int* ptr2;
You lose size information when you refer to arrays as pointers. There is no way you can identify the size of the array i.e. the number of elements using ptr1. You have to take help of another variable which will denote the size of the array referred by ptr1 (or ptr2).
Same holds for character arrays as well. Consider the below:
char some_string[100];
strcpy(some_string, "hello");
The approach you mentioned of checking for \0 (or 0) gives you the number of elements which are part of the string residing in some_string. In no way does it refer to the number of elements in some_string which is 100.
To identify the size of destination, you have to pass another argument depicting its size.
There are other ways to identify the end of the array but t is cleaner to pass the size explicitly rather than using some pointer hack like passing a pointer to end of the array or using some invalid value as the last element in array.
TL/DR - You will need to pass the array size as a separate parameter to your function. Sentinel values like 0 only mark the logical end of a sequence, not the end of the array itself.
Unless it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. So when you pass your source and destination arrays as arguments to copy, what the function actually receives is just two pointers.
There's no metadata associated with a pointer that tells it whether it's pointing to the first object in a sequence, or how long that sequence is1. A sentinel value like the 0 terminator in strings only tells you how long a logical sequence of values is, not the size of the array in which they are stored2.
You will need to supply at least one more parameter to copy to tell it how large the target buffer is, so you stop copying when you've reached the end of the target buffer or you see a 0 in the source buffer, whichever comes first.
The same is true for array objects - there's no runtime metadata in the array object to store the size or anything else. The only reason the sizeof trick works is that the array's declaration is in scope. The array object itself doesn't know how big it is.
This is a problem for library functions like strcpy, which only receives the starting address for each buffer - if there are more characters in the source buffer than the target is sized to hold, strcpy will blast right past the end of the target buffer and overwrite whatever follows.
I was reading a csc placement paper where I read a question related to c language array's sizeof() operator. Answer was something else then i expected it to be.
int DIMension(int array[]) {
return sizeof(array )/ sizeof(int);
}
main() {
int arr[10];
printf(“Array dimension is %d”, DIMension(arr));
}
This program in c language prints 1 as the answer. Why is that happening?
Because int array[] is just a pointer and it's size is same as of int.
I think you expected that size of arr will somehow be passed to function, but it doesn't work that way. Size of arr can be determined only in same scope where it was declared, because sizeof actually works at compile time.
The array is passed as a pointer. There is no way for the function to know how much space was allocated to the array.
All arrays decay to pointers when they are passed around, so the expression becomes:
sizeof(void*)/sizeof(int)
which equates to 1 on 32bit machines with 32bit ints and 2 on 64bit machines with 32bit ints.
You need to pass the length to the function, or create a struct that includes both a pointer to the array and the length of the array. There is no size information stored with C arrays.
An array in C is a very fragile type. There are many situations in which an array decays to a pointer to the first element, and passing an array as an argument of a function is such a situation. Behold:
int main()
{
char data[10]; // sizeof(data) == 10
return call_me(data); // data is equivalent to &data[0] here!
}
int call_me(char x[])
// int call_me(char * x) // same thing!
{
// here sizeof(x) == sizeof(char *)
// ...
}
Arrays are peculiar in C in the sense that they cannot be passed as function arguments or returned from functions, so you will frequently see pointers when you expect arrays. It is the responsibility of the caller (you!) to provide enough information to interpret a pointer as an array correctly.
Note that a common C idiom creates an "array" dynamically entirely without ever mentioning an array type: char * p = malloc(10); Here p is never anything but a pointer, and it is entirely up to you to remember that you can treat it as an array.
(The situation is a little better in C++, where you can pass actual arrays by reference.)
See the syntax for the function defination can be written following way
int DIMension(int array[]) {
return sizeof(array )/ sizeof(int);
}
int DIMension(int *array)
{
return sizeof(array )/ sizeof(int);
}
int DIMension(int array[10])
{
return sizeof(array )/ sizeof(int);
}
All these three statement has same meaning and common thing across the three is the argument array which is nothing but a pointer to array which is always gonna to be 4 bytes
Is this possible?
size_t calculate(char *s)
{
// I would like to return 64
}
int main()
{
char s[64];
printf("%d", calculate(s));
return 0;
}
I want to write a function which calculates the size of the char array declared in main().
Your function calculate(), given just the pointer argument s, cannot calculate how big the array is. The size of the array is not encoded in the pointer, or accessible from the pointer. If it is designed to take a null-terminated string as an argument, it can determine how long that string is; that's what strlen() does, of course. But if it wants to know how much information it can safely copy into the array, it has to be told how big the array is, or make an assumption that there is enough space.
As others have pointed out, the sizeof() operator can be used in the function where the array definition is visible to get the size of the array. But in a function that cannot see the definition of the array you cannot usefully apply the sizeof() operator. If the array was a global variable whose definition (not declaration) was in scope (visible) where calculate() was written - and not, therefore, the parameter to the function - then calculate() could indicate the size.
This is why many, many C functions take a pointer and a length. The absence of the information is why C is somewhat prone to people misusing it and producing 'buffer overflow' bugs, where the code tries to fit a gallon of information into a pint pot.
On statically declared char[] you can use operator sizeof, which will return 64 in this case.
printf("%d", sizeof(s));
On dynamically declared char*, it is not possible to get the size of the allocated memory.
Dynamic arrays are obtained through malloc and friends. All the others are statically declared, and you can use sizeof on them, as long as you use it in the same scope as the array was declared (same function, in your case, for example).
Yes, it's possible if s has a specific character in the end of it's array. For example you could have s[63] = 125 and by knowing that every other character from 0 to 62 won't be 125, you can do a for loop until you find 125 and return the size of the array.
Otherwise, it's not possible, as s in the function parameter is just a pointer to your array, so sizeof(s) inside calculate will only return your machines pointer size and not 64 as someone could expected.
Unfortunately, you cannot determine from a pointer value alone how many elements are in the corresponding array. You either need some sort of sentinel value in the array (like the 0 terminator used for strings), or you need to keep track of it separately.
What you can do is get the number of bytes or elements in an array using the sizeof operator:
char arr[64];
size_t size = sizeof arr; // # of bytes in arr
size_t count = sizeof arr / sizeof *arr; // # of elements in arr
However, this only works if arr is an array type; if you tried to do this in your function
size_t calculate(char *s)
{
return sizeof s;
}
it would return the size in bytes of the pointer value, not of the corresponding array object.
No. char *x or char x[] just creates a pointer to a memory location. A pointer doesn't hold any information about the size of the memory region.
However, char *x = "Hello" occupies 6 bytes (including the terminating null), and strlen(x) would return 5. This relies on the null char at the end of the string, strlen still knows nothing about the underlying buffer. So strlen("Hello\000There") would still be 5.
This is usually done with a macro in C, like:
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
Whether it's a good idea is a totally different question.