s[ ] is an array.&s should give address of decayed pointer [duplicate] - c

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.
After initialising character array name and address refers to same. s[] is an array. so it decays to pointer s, &s should give the address of pointer s
#include <stdio.h>
int main()
{
char s[]="Get Organised! learn C!";
printf("%u %s\n",&s[2],&s[2] );
printf("%u %s\n",s,s ); /* This line and below line is equivalent*/
printf("%u %s\n",&s,&s ); /* Please Explain */
printf("%u %s\n",s[2],s[2] );
printf("%u %s\n",s[3],s[3] );
return 0;
}
%u is just used to see what is going inside.

Getting rid of undefined behaviour first:
int main() {
char const string [] = "hello";
printf("%p %p\n", (void *) string, (void *) &string);
return 0;
}
You get (probably, that's target dependent) the same address printed here because the first expression is implicitly converted to a pointer to the first element of the array while the second is a pointer to the whole array (which most likely happens to start at its first element)
string == &(string[0]) // this is often called decaying
The type of the expression string (or more precisely the expression it decays to) is char const * whereas the type of &string is char const (*array)[6], so they're not "the same".
The reason that &string is not a pointer to a pointer is simple: The C standard explicitly forbids array expressions prefixed with the address of operator (&) (or inside an sizeof operator) to be implicitly converted to a pointer.

With the below, s is an array 100 of char. When is is passed to printf(), array s is converted to the value and type of the address of first element. So printf() is given a char *.
&s is the address of an array 100 of char. It has an equivalent value as s, yet a different type.
char s[100]="Whatever";
printf(some_format,s);
printf(some_format,&s);
To properly print addresses of variables, literals, cast to (void*) and use "%p". The print out typically lacks any description of the type of the variable.
printf("%p\n",(void*) s);
printf("%p\n",(void*) &s);
Output
0x28cbdc
0x28cbdc
To see an effect of the type difference:
printf("%zu\n",sizeof *(s));
printf("%zu\n",sizeof *(&s));
Output
1
100
#john bode also suggested this earlier.

Related

How does printf("%s\n", x) work, if x is of type char * instead of char[N]?

Some example code:
#include <stdio.h>
void func0(char *x)
{
printf("func0, %s, %zu\n", x, sizeof(x));
}
//for comparison with func0
void func1(char **x)
{
printf("func1, %s, %zu\n", *x, sizeof(*x));
}
int main()
{
char x[10] = "hello";
printf("%s, %zu, %zu, %zu\n", x, sizeof(x), sizeof(*x), sizeof("hello"));
func0(x);
func1(&x);
return 0;
}
For func1() (for comparison with func0), there is a "warning: incompatible pointer types passing 'char (*)[10]' to parameter of type 'char **'" and "Segmentation fault" error.
But for func0(), isn't the type 'char [10]' converted to 'char *'? If so, how is printf("%s") still able to print out "hello"? As shown in the output of func0():
hello, 10, 1, 6
func0, hello, 8
Is the information of length (i.e. N of char[N]) passed to func0?
What is the difference between x in func0 and *x in func1? Aren't they both an address pointing to a char?
Thank you very much.
[EDIT] Thank you so much for the detailed answers!
Let me summarise the warning and error for func1().
char x[10] = "hello";
The type of &x is char (*)[10], which is a pointer to an array, not pointer to pointer (e.g. char **). Hence the warning.
x is already the address (pointing to the string), and you can only take the address of an actual memory space. &x is not the address of x. **x in func1(): trying to read from an illegal address (the value of "H" in this example?), hence the Segmentation fault.
The extra question is:
What is the use case for using &x (e.g. char (*) [N])?
I see the difference between x and &x, char * / char[N] vs. char (*) [N], but I cannot figure out a case when you have to use char( *) [N]. x and &x are the same address after all.
there is a "warning: incompatible pointer types passing char (*)[10] to parameter of type char **" and "Segmentation fault" error.
That's right, &x expression produces a pointer to array of ten characters, hence the warning. If you want to pass a pointer to pointer, make a pointer, and take a pointer of it:
char *px = x; // alternatively you could write &x[0]
func1(&px);
But for func0(), isn't the type char [10] converted to char *?
That's right, character array "decays" to character pointer when you make a function call.
how is printf("%s") still able to print out "hello"
This is possible because x contains a null-terminated sequence of characters. Therefore, printf does not need to know the size of the array when processing %s: stopping at '\0' is sufficient.
Essentially, %s does not need to know the size of the array, it needs to know the length of the string, in the same way strlen "knows" it:
printf("func0, %s, %lu\n", x, strlen(x));
// Prints hello 5
I see the difference between x (char / char[N]) and &x, but I cannot figure out a case when you have to use char(*) [N]
Here is a small example:
void print_many(char (*rows)[10], size_t count) {
for (size_t i = 0 ; i != count ; i++) {
printf("%zu: %s\n", i+1, rows[i]);
}
}
you call it like this:
char rows[10][] = {"quick", "brown", "fox"};
print_many(rows, 3);
Demo.
Is the information of length (i.e. N of char[N]) passed to func0?
No. The parameter for func0 is char *. This is a pointer to char, nothing else. There is no length associated with it.
But for func0(), isn't the type 'char [10]' converted to 'char *'?
Yes. When x, which has type char [10], is used as a function argument, it is automatically converted to a pointer to its first argument. So the function receives a pointer to char.
If so, how is printf("%s") still able to print out "hello"?
The pointer passed to printf must point to the first character of a string whose end is marked by a null character. Thus, the pointer it receives points to a char containing 'h', after which there is a char containing 'e', then 'l', then 'l', then 'o', then zero. printf prints characters one by one until it sees the zero.
What is the difference between x in func0 and *x in func1?
If func1 were passed a pointer to a pointer to char, then using *x to pass a pointer to char to printf could be okay. However, your call to func1 is func1(&x). This is not passing a pointer to a pointer to a char. Since x is an array of 10 char, &x is a pointer to an array of 10 char. It is not a pointer to a pointer.
An array is not a pointer. Although arrays are often automatically converted to pointers, this automatic conversion does not happen when the array is the operand of unary &. (It also does not happen when the array is the operand of sizeof or _Alignof, or when the array is a string literal used to initialize an array.)
To produce a pointer to a pointer to char from the array x, you would have to take the address of a pointer to its first character. There is no way to do this in a simple expression, because x is the array, not a pointer. You could create a pointer to its first character with char *y = x;, and then you could pass &y to func1.
Note
Do not print sizes from sizeof using %lu. Use %zu. The z modifier is specifically for the size type, size_t.
For the question in the title, print("%s\n", x) does not care if x is a pointer or an array, as long as it contains a zero-terminated string.
Next, only the topmost dimension of an array can be transparently coerced to a pointer, that's what the warning about.
Finally, &x points to the zero elements of your array, so when you dereference it in func1, array's first few elements (might be even eight of them, so two the rightmost are not even initialized) are reinterpreted as a pointer-to char which almost certainly points to nowhere. That's how the segfault arised.

Printing pointer raises a runtime error [duplicate]

This question already has answers here:
What exactly is meant by "de-referencing a NULL pointer"?
(8 answers)
Closed 5 years ago.
I am studying C at school , and I am facing a problem with pointers , Why does this unhandled error rise (im using visual studio 2013 express for desktop on 64 bit windows 10) , when I try to run the code below.
My question is , Why is this happening?
Code Block :
// ~~ Libraries Or Header Files. ~~ //
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ~~ Main Function ~~ //
int main(void)
{
// ~ Variables ~ //
int * p = NULL;//#define NULL ((void *)0)
printf(*p);
//printf(p)l also raises an error.
// ~ END ~ //
system("PAUSE");
return 0;
}
Error:
" Unhandled exception at 0x009A3C2A in hwQ3.exe: 0xC0000005: Access violation
reading location 0x00000000 ".
There are two problems with this code.
First, printf expects its first argument to be a format string, and the type of the argument is assumed to be const char * (it's a pointer to the first character in a zero-terminated string). Since the object p has type int *, the expression *p has type int, so it's the wrong type, and the value of *p isn't a valid address of a string, because...
You've initialized p to NULL. NULL is an invalid pointer value that's guaranteed to compare unequal to any valid pointer value (it's a well-defined "nowhere" value). When you write *p, you're saying, "I want the value of the integer object p points to." Since p points "nowhere", the behavior of the operation is undefined, and one possible result of undefined behavior is a segfault.
So...
If you want to print the value of the integer object that p points to, you would write something like
printf( "%d\n", *p );
but only after you do a sanity check on p to make sure it isn't NULL:
if ( p ) // or p != NULL
printf( "%d\n", *p );
Valid pointer values are obtained by one of the following methods:
Using the unary & operator on an lvalue (an expression that refers to an object in memory such that the object may be read or updated):
p = &x; // x is an integer object
p = &a[i]; // a is an array of integer, so a[i] is an integer object
p = &foo.bar; // foo is a struct with an int member named bar, so foo.bar is an integer object
etc.
Calling one of malloc, calloc, or realloc:
p = malloc( sizeof *p );
Using an array expression in most circumstances. Unless it is the operand of the sizeof or unary & operators, or is a string literal being used to intialize 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. In the case of printf, when we write
printf( "this is a test\n" );
the type of the string literal "this is a test\n" is converted from type "16-element array of char" to "pointer to char", and its value is the address of the first character in the string - that address value is what actually gets passed to printf.
The first argument to printf(...) is a const char *format so in both cases you're trying to dereference a NULL pointer. That causes you to access memory outside your allowable range (at zero).
Basic information about pointers:
Pointers are to declare a pointer variable, set it to point somewhere, and finally manipulate the value that it points to. A simple pointer declaration looks like this:
int *ip;
Pointers are generated with the address-of'' operator &, which we can also think of as thepointer-to'' operator. Demonstrating this by declaring (and initializing) an int variable i, and then setting ip to point to it:
int i = 5;
ip = &i;
Example pointer usage:
#include <stdio.h>
int main(){
int var =10;
int *ptr = &var;
printf("%d\n", *ptr);
return 0;
}
What happens when you deference the pointer to NULL?
int *a = NULL; // a is a null pointer
int b = *a; // CRASH: dereferencing a, trying to read it
*a = 0; // CRASH: dereferencing b, trying to write it

what is the difference between accessing an array with a pointer and a non-array variable through a pointer

I am attempting to learn C in a little more depth. I have written the code displayed below.
#include "includes.h"
int main() {
char *array[1];
array[0] = "cloud";
char *ll[1];
ll[0] = array[0];
int n = 20, *pointer; // actual and pointer decaration
pointer = &n; // assign the memory address of int n to pointer
printf("the address of the variable in pointer is: %x\n", pointer);
printf("the value of *pointer is %d\n", *pointer);
printf("the value of &pointer is %x\n", &n);
//return 0;
// to access the value provided by a pointer, you would use *pointer
// accessing an array directly
printf("value of array[0] %s\n", array[0]);
printf("address of &array[0] %x\n", &array[0]);
// accessing array through the pointer ll
printf("value of *ll %s\n", *ll);
printf("address of ll %x\n", ll);
printf("pointer: %p\n", (void*) pointer); //inclusion from #chux
}
The header file "includes.h" contains the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#define DEF1 20
#define DEF2 2
Here is the program output, as from my Bash Terminal:
[carl#sparknohss c]$ ./pointers.bin
the address of the variable in pointer is: 4a8c27dc
the value of *pointer is: 20
the value of &pointer is: 4a8c27dc
value of array[0]: cloud
address of &array[0]: 4a8c27f0
value of *ll: cloud
address of ll: 4a8c27e0
pointer: 0x7ffc4a8c27dc
[carl#sparknohss c]$
I see that there is a difference, at least I think, when accessing a pointer that points to a non-array and when accessing a pointer that points to an array. Is there anyone that can explain this in a little more detail?
Also, what is the difference between %x and %p, other than the '0x7ffc' prefix provided by %x? Are there any good resources that I can delve into for a better explanation?
I see that there is a difference, at least I think, when accessing a pointer that points to a non-array and when accessing a pointer that points to an array. Is there anyone that can explain this in a little more detail?
There are some differences when dealing with arrays and pointer objects.
Setting aside your code for a second, assume you have the declaration
int arr[10];
This creates an array arr large enough to hold 10 integers; it's laid out in memory like so:
+---+
arr: | | arr[0]
+---+
| | arr[1]
+---+
...
+---+
| | arr[9]
+---+
One thing becomes obvious here - the address of the first element of the array (&arr[0]) is going to be the same as the address of the whole array object (&arr). The expressions &arr[0] and &arr will have the same value, but their types will be different - the type of &arr[0] will be "pointer to int" (int *), while the type of &arr will be "pointer to 10-element array of int" (int (*)[10]).
Now here's where a wrinkle comes in - except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize another array in a declaration, an expression of type "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.
This means that the expression arr also evaluates to the address of the first element of the array, just like &arr[0] and &arr; it "decays" from type "10-element array of int" to "pointer to int" (same type as &arr[0]).
This is definitely different from how regular pointer variables behave. Given
int *ptr;
the expression ptr does not give you the same value as &ptr - it gives you the value of whatever is stored in ptr.
Going back to your code for a second, in the line
array[0] = "cloud";
the string literal "cloud" is itself an array expression - it has type "6-element array of char" (counting the 0 terminator). Since it is not the operand of the sizeof or unary & operators, nor is it being used to initialize another array in a declaration, the expression is converted from type "array of char" to "pointer to char", and the value of the expression is the address of the first character in the string. Since you declared array as an array of char *, this works; the type of array[0] is char *.
So, why do array expressions "decay" to pointer expressions?
The array indexing operation a[i] is defined as *(a + i) - given an address value, offset i elements (not bytes) from that address and dereference the result. This is a holdover from the B programming language from which C was derived, and which used pointers internally when setting up array objects. C got rid of the internal pointers, but kept the subscript semantics. So, for a[i] to work in C, a first has to be converted to a pointer value. Note that this means you can use the [] operator on pointer types - pointer[0] and *pointer will give you the same result (the value of the thing pointer is pointing to).
So, if you print out the following expressions:
printf( "&array[0] = %p\n", (void *) &array[0] );
printf( "array = %p\n", (void *) array );
printf( "&array = %p\n", (void *) &array );
you should see the same value for all three - the address of the first element of array. If you print out the expression
printf( "array[0] = %p\n", (void *) array[0] );
you should see the address of the first character of the "cloud" string literal.
If you print the expression
printf( "array = %s\n", array );
you should see the string cloud. Remember that the %s conversion specifier expects its corresponding argument to be a pointer to char, and it will print the sequence of characters starting at that address until it sees the 0 terminator.
If you print the expression
printf( "*array[0] = %c\n", *array[0] );
you will see the character c - the first letter in the "cloud" string. Note that *array[0] is the same as array[0][0]. To print l, you'd write
printf( "array[0][1] = %c\n", array[0][1] );
If you print the expressions
printf( "pointer = %p\n", (void *) pointer );
printf( "&pointer = %p\n", (void *) &pointer );
you should definitely see different values since pointer is not an array object.
Also, what is the difference between %x and %p
%x expects its corresponding argument to have type unsigned int, and formats the output in hexadecimal.
%p expects its corresponding argument to have type void *, and formats the output in an implementation-defined manner (often hex, but it doesn't have to be).
You do not want to use %x (or anything other than %p) to print out pointer values. For one thing, a pointer value may be wider than an unsigned int (that's true on my system), so the output will likely be garbled.

sizeof() function in C [duplicate]

This question already has answers here:
What does sizeof(&array) return?
(4 answers)
Closed 9 years ago.
main()
{
char a[] = "Visual C++";
char *b = "Visual C++";
printf("\n %d %d",sizeof(a),sizeof(b));
printf("\n %d %d",sizeof(*a),sizeof(*b));
}
sizeof(a) gives me output: 11 ( that is length of the string)
Why is it so ?
Why isn't the output sizeof(a)=4 since when I try to print a it gives me an address value and hence an integer?
Whenever you refer to the name of the array in your program, It normally decays to a pointer to the first element of the array. One of the exception to this rule is the sizeof operator. So when you consider the following code.
int main()
{
char a[] = "Visual C++";
printf("sizeof(a)=%d\n",sizeof(a)); /* Here sizeof(a) indicates sizeof array */
printf("a=%p",a); /* Here the array name, passed as an argument to printf decays into a pointer of type (char *) */
return 0;
}
In the declaration char a[] = "Visual C++", a is an array of 11 char. So its size is 11 bytes.
In the declaration char *b = "Visual C++", b is a pointer to char. So its size is four bytes (in the C implementation you are using).
In the expression printf("%s", a), a is also an array. However, it is automatically converted to a pointer to the first element of the array. So a pointer to char is passed to printf.
This conversion happens automatically unless an array is the argument of &, sizeof, or _Alignof or is a string literal used to initialize an array of char. Because it happens automatically, people tend to think of array names as pointers. However, they are not.
Incidentally, sizeof is an operator, not a function.
When sizeof is applied to the name of a static array (not an array allocated through malloc), the result is the size in bytes of the whole array. This is one of the few exceptions to the rule that the name of an array is converted to a pointer to the first element of the array, and is possible just because the actual array size is fixed and known at compile time, when sizeof operator is evaluated.
There are lots of errors, here.
"sizeof(a) gives me output: 11 (length of the string)"
The length of the string is 10, not 11. sizeof(a) gives you the length of the array.
"why is it so, why isn't the output sizeof(a)=4 since when I try to print a it gives me an address value"
Here are two methods of "printing a" which do not "give you an address value":
puts(a);
and:
printf("%s\n", a);
so your logic is flawed, and this is the source of your confusion. "Printing a" only "gives you an address value" when you explicitly or implicitly elect to do so.
sizeof(a) gives 11 in this case because the C language defines the sizeof operator to give you the size of an array when an array is the operand. This, I'd argue, is the most natural behavior people would expect, so presumably that's why it is defined as such.
"and hence an integer."
In any case, an address is an address, not an integer. At best you could argue that it ought to give you the size of a pointer, but certainly not the size of an integer.

referencing an index value of a character in a pointer string in c

Suppose I have something like this
int strLen;
printf("Please enter a number: ");
scanf("%d", &strLen);
char *myString;
myString = (char*) malloc(strLen*sizeof(char));
then you fill string with something like "Hello World!" but now I want to just print out "World!" Since my string is just a pointer reference, I can't call it out by indexes ie.
for(int i=6;i<strLen;i++)
{
printf("%s", myString[i]);
}
// THIS IS AN INCORRECT WAY TO DO THIS
How could I refer to a specific character or even pass the array onto another function of the program if all I have is the array base pointer? Can I ever get the full functionality as if I declared it as a static array before compile time?
How could I refer to a specific character or even pass the array onto another function of the program if all I have is the array base pointer?
Several things to remember:
Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be replaced with ("decay to") an expression of type "pointer to T" whose value is the address of the first element of the array;
In the context of a function parameter declaration, T a[N] and T a[] are identical to T *a (IOW, a will be declared as a pointer to T, not an array of T - note that this is only true for function parameter declarations);
The subscript operation a[i] is defined as *(a + i) - start with a base address specified by the pointer expression a, offset by i elements (not bytes), and dereference the result;
In C, you do not need to cast the result of malloc (or calloc or realloc), since it returns a value of type void *, which may be assigned to any other object pointer type. Adding the cast may suppress a useful diagnostic if you forget to include stdlib.h or otherwise don't have a prototype in scope. Note that this is not true for C++ - a cast is required there, but if you're writing C++ you should be using new instead of malloc anyway.
This is a long-winded way of saying that, in many contexts, array expressions and pointer expressions can be treated the same way. Taking printf as an example:
int main(void)
{
char foo[] = "This is a test";
char *bar = foo;
printf("%s\n", foo);
printf("%s\n", &foo[0]);
printf("%s\n", bar);
return 0;
}
printf expects the argument corresponding to %s to have type char *, or "pointer to char", not "array of char". The three printf calls above are all equivalent. In the first call, foo is an array expression with type "15-element array of char". By the first rule mentioned above, it will be replaced with an expression of type "pointer to char" whose value is the address of the first element. The second and third calls pass the pointer value directly, just using different expressions to accomplish the same effect.
As far as printf is concerned, all three expressions yield the same result -- the address of the first element of a sequence of char values, terminated by 0.
What does this mean for your code? Well, for one thing, you can use the subscript operator on mystring as though it were an array type:
printf("%s\n", &mystring[6]); // prints "World!"
Note that the subscript operator [] has higher precedence than the unary & operator, so the above is interpreted as &(mystring[6]) - we subscript into mystring and then take the address of the result.
You can pass mystring to any function that you would pass an array of char to:
void foo(char str[]) // identical to char *str
{
// do something with str
}
...
int main(void)
{
char str[] = "Hello, World!";
char *mystr = malloc(strlen(str) + 1); // note no cast
strcpy(mystr, str);
foo(str);
foo(mystr);
...
}
Again, as far as the function foo is concerned, its argument is type char *, not array of char. The expression str decays to a pointer value, and mystr is a pointer value to begin with.
A couple of things:
1) Allow for the null terminator in your "malloc()":
int strLen;
...
char *myString = (char*) malloc(strLen+1);
2) The "sizeof(char)" is kind of duplicate redundant. No harm - but no purpose, either. So I omitted it.
3) This is wrong:
for(int i=6;i<strLen;i++)
{
printf("%s", myString[i]);
}
4) This is better:
for(int i=6;i<strLen;i++)
{
printf("%c", myString[i]);
}
You can take the address of the character at a certain array index.
So, try this if you just want to print out 'world!':
#include <stdio.h>
int main(int a, char** b)
{
int strLen;
char *myString;
myString = "hello world!";
printf("%s", &myString[6]);
return 0;
}

Resources