This question already has answers here:
In C, are arrays pointers or used as pointers?
(6 answers)
Closed 6 years ago.
Yes, it has been asked before, many times, but I wanna know which one is more advisable?
typedef struct {
int a;
int addr[8];
} usr_command;
usr_command* p_usr_command;
int foo(int* parameter)
{}
So which one is less prone to be problematic?
foo(p_usr_command->addr);
or
foo(&p_usr_command->addr[0]);
?
In this case ( passing an array name vs. passing the address of the first object in the array as function argument), both the snippets are equivalent.
Quoting C11, chapter §6.3.2.1, Lvalues, arrays, and function designators (emphasis mine)
Except when it is the operand of the sizeof operator, the _Alignof operator, or the
unary & operator, or is a string literal used to initialize an array, an expression that has
type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points
to the initial element of the array object and is not an lvalue. [....]
However, in general, they are not the same.
array is an array of type int [8]
&(array[0]) is a pointer, type int *
As already suggested by EOF in his comment, try passing both variants to the sizeof operator and check the result to get the hands-on output.
Related
I am currently studying C language.
I wonder what 'array decaying' means, and when it happens.
And I wonder if the two variables below are interpreted in the same way.
char(*zippo)[2] = NULL;
char zippo2[4][2];
zippo = (char(*)[2])malloc(sizeof(char[2]) * 4);
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
The two variables below
char(*zippo)[2] = NULL;
char zippo2[4][2];
have different types. The first one is a pointer to an object of the type char[2]. The second one is a two-dimensional array with four elements of the type char[2].
When the array zippo2 is used in expression except the expressions listed in the quote (as for example using it with the sizeof operator) then its designator is implicitly converted to pointer to its first element and has the same type as the variable zippo.
This question already has answers here:
How come an array's address is equal to its value in C?
(6 answers)
Closed 6 years ago.
So I almost went all hurr durr on my classmates when they wrote that
&array gives you address of the first element
But turns out they are right. This sounds like inconsistency to me. We're talking about array defined like this:
int numbers[] = {1,2,3,4};
The variable numbers is (I think) then of type int* const. I'd think that pointer to that would be int** const. But apparently this expression evaluates as true:
if(&numbers == numbers) {
printf("Pointer to array is still the same array!\n");
}
And of course, this then also is true:
int* first_elm_ptr = &numbers;
if(*first_elm_ptr == *numbers)
printf("%d == %d\n", *first_elm_ptr, *numbers);
So apparently you cannot get a pointer to the variable holding address of that array. Expression &numbers is essentially meaningless. Maybe it is even removed by compiler.
How's that possible? I am very confused right now! How does standard explain this behaviour? I made an ideone test code to verify this: http://ideone.com/pYffYx
The address of an array and the address of the first element of the array are essentially same value (same address location). They differ in type.
Expression &numbers is essentially meaningless
No, it is not.
In your case,
&numbers is of type int (*) [4]
numbers is of type int [4], and in some casesNote, it decays to int *.
Note:
Quoting C11, chapter §6.3.2.1
Except when it is the operand of the sizeof operator, the _Alignof operator, or the
unary & operator, or is a string literal used to initialize an array, an expression that has
type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points
to the initial element of the array object [....]
This question already has an answer here:
Exceptions to array decaying into a pointer?
(1 answer)
Closed 9 years ago.
I am preparing some presentation and I am curious if there is any other context (except of sizeof) where a variable of array type gives different behavior than a pointer to the first element of the array. I mean:
int a[5];
int *p = a;
printf("%d %d\n", sizeof(a), sizeof(p));
prints two different numbers. Is there any other similar situation where it matters whether I use an array or a pointer?
Is there a situation when an array is not converted to pointer except of sizeof?
From C99/C11, section 6.3.2.1:
Except when it is the operand of the sizeof operator, [the _Alignof operator,] or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type"...
Note that _Alignof is only in C11.
Is there any other similar situation where it matters whether I use an array or a pointer?
The above rule explains everything about the behaviour of arrays vs. pointers. However, there are several less-than-obvious implications of the conversion it describes.
For example, this doesn't compile:
void foo(int **a) { }
int b[5][10];
foo(b); // Compilation error; b becomes &b[0], which is pointer type,
// and thus doesn't then become &&b[0][0]
And neither does this:
int a[5];
int b[5];
a = b; // Compilation error; a becomes &a[0], which isn't an lvalue
One more thing.
int a[10];
int *pa;
There is one difference between an array name and a pointer that must
be kept in mind. A pointer is a variable, so pa=a and pa++ are legal.
But an array name is not a variable; constructions like a=pa and a++
are illegal.
The C programming language, Dennis M. Ritchie
There are a few other contexts where it is not converted such as unary &, if we look at the draft C99 standard section 6.3.2.1 Lvalues, arrays, and function designators paragraph 3 it says:
Except when it is the operand of the sizeof operator or the unary & operator, or is a
string literal used to initialize an array, an expression that has type ‘‘array of type’’ is
converted to an expression with type ‘‘pointer to type’’ that points to the initial element of
the array object and is not an lvalue.
This question already has answers here:
Length of array in function argument
(9 answers)
Closed 9 years ago.
#include<stdio.h>
void printS(char []);
int main(){
char str[]="The C Programming Language";
printf("%d \n",sizeof(str)); //output=27
printS(str);
}
void printS(char s[]){
printf("%d \n",sizeof(s)); //output=4
}
Why this anamolous output
please explain what is the difference between 'str' and 's'....
and how can i have sizeof() output=27 in printS function.
When you pass an array to a function like you are it will decay to a pointer and therefore sizeof will be returning the size of a pointer not the size of the array. The C Faq's section on Arrays and Pointers is a great reference and Question 6.4 covers this exact issue. The relevant section of the C99 draft standard is section 6.3.2.1 Lvalues, arrays, and function designators paragraph 3 which says(emphasis mine):
Except when it is the operand of the sizeof operator or the unary & operator, or is a
string literal used to initialize an array, an expression that has type ‘‘array of type’’ is
converted to an expression with type ‘‘pointer to type’’ that points to the initial element of
the array object and is not an lvalue.
In order to obtain the length of a C style string you can use strlen from string.h header file.
The value of sizeof() is the size of one variable of the specified type. s is actually char*, so sizeof(s) is 4 (on your 32-bit platform). In main(), str is treated as an array of char, so sizeof(str) is the size of the array. Note that the length of "The C Programming Language" is 26, the extra one byte is for the zero terminator.
To get the length of s, use strlen(s). This time the zero terminator is not counted. And don't forget to #include <string.h> at the beginning.
C does not have the feature of passing array values. Arrays are always passed as pointers, when you declare a parameter of type foo[] you are effectively declaring foo *.
This question already has answers here:
In C, are arrays pointers or used as pointers?
(6 answers)
Closed 9 years ago.
When the array variable is considered as pointer and when it is considered as simple array in C? As example sometimes sizeof(array_variable) operator returns the address size and sometimes it returns the size of the array.
C 2011 (N1570) 6.3.2.1 3:
Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
C 2011 (N1570) 6.7.6.3 7:
A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation.
In a function argument, an array ([]) or [...]) is equivalent to a pointer (*). So sizeof(myarg) == sizeof(void*) is true for void f(char *myarg);, void f(char myarg[]); and void f(char myarg[42]);.
In global and local variables, an array is different from a pointer. sizeof(...) reflects that difference.
An array can always be converted to a pointer automatically (but not the other way round), and the address of the first element is used, i.e. ary is converted to &ary[0].
Always it is treated as pointer .
when you use array name without index , it will give the base address of the array . When you use the array name with index , it will be treated as *(array name + index) . It gives the indexe-th element from the base address . *array means first element .
name of an array variable is always a pointer. It is the specilization of sizeof() that it returns the size of an array if applied to an array variable.