-2

I define b as pointer to string:

char a[] = "hello";
char *b;
strcpy(&b, a);

So far so good (although I don't quite understand why b=&a doesn't work, considering that both a and b are pointers).

Now when I want to print the string pointed to by b, I have to use &b:

printf("%s", &b);

Why do I need to give address of a pointer to printf(), in order for contents of the variable that this pointer points to be printed?? Why printf("%s", *b) doesn't work?

Contrast this with syntax for pointer to integer:

int c = 5;
int *d;
d = &c;
printf("%d\n", *d);

Makes full sense.

I am aware that strings syntax is different in a sense that string name is also a pointer. Not sure I understand why such special rule for strings is required though, but fine, after banging my head against the wall few times, I forced-learned this. But printf("%s", &b), really?

I can learn this as "it's a rule", however I'd appreciate if someone helps me make sense of it.

  • 1
    Your first snippet is not correct. `b` is already a pointer. Using `&b` results in pointer to pointer which is not what `strcpy` expects. This will cause undefined behaviour. Your further example using `&b` in `printf` is also wrong and a result of this first error. – Gerhardh Dec 03 '20 at 13:32
  • The compiler does not think `strcpy(&b, a);` is correct: warning C4047: 'function': 'char *' differs in levels of indirection from 'char **'. Similar warning for `printf("%s", &b);` where you need `printf("%s", b)` Both functions expect a pointer, which the `b` from `char *b;` is. – Weather Vane Dec 03 '20 at 13:33
  • 1
    @WeatherVane 's comment is a bit misleading. `&b` is also a pointer, so merely saying "Both functions expect a pointer" is odd. The problem is that `&b` is a pointer of the wrong type. `&b` is a `char **`, and strcpy expects the first parameter to be of type `char *` – William Pursell Dec 03 '20 at 13:46
  • Thanks for comments! If instead of I write , how compiler knows whether b is single char or a pointer to string. Will it figure it out only after I initialize b? What is the proper code to point b to string a, and print that string using b as argument of printf()? – metodije Dec 03 '20 at 13:59
  • @CyberSinke Declaring `char b` already tells the compiler that `b` is a variable of fundamental data type `char`. No, it(compiler) will figure out as soon as it reaches the line `char b;`. **Proper code:** `char *b = a;` and then `printf("%s", b);`. :-) – Shubham Dec 03 '20 at 14:39

3 Answers3

1

You are invoking undefined behavior. In the code

char a[] = "hello";
char *b;
strcpy(&b, a);  /* ERROR */

You are attempting to write the contents of a to the variable which very likely is not large enough to hold it. If a char * is 6 bytes or more, the code will "work", but it's not doing at all what you think. b should hold the address of a char, but instead it now holds garbage data which you are interpreting as a string. When you write printf("%s", b), the compiler will try to interpret that string as an address and the output will be garbage. But when you write printf("%s", &b), you are essentially lying to the compiler and telling it to treat the contents of b as a string. The compiler will almost certainly emit warnings for this, and if you are not getting warnings you need to turn up the diagnostics. (eg, add -Wall -Wextra).

Quite likely what you actually want is something like:

char a[] = "hello";
char *b = malloc(strlen(a) + 1);  /* Error check omitted */
strcpy(b, a);
printf("%s", b);
William Pursell
  • 204,365
  • 48
  • 270
  • 300
1

although I don't quite understand why b=&a doesn't work,

Its wrong to assign address of array to pointer in this case, just b = a is enough, since a indicates the base address of array .

Now when I want to print the string pointed to by b, I have to use &b:

printf("%s", &b);

the above usage is also wrong , char *b; is a pointer you will have to allocate memory before using pointers, by default they do not point to proper memory location

strcpy(&b, a);

Even this is also wrong, look at strcpy, which accepts char* and const char* for destination and source, what you are passing is char**(&b) and char*

Why printf("%s", *b) doesn't work?

*b is a char here, so this likely to crash.

int c = 5;
int *d;
d = &c;

this above case is fine because pointer variable d is having address of c. using *d without assigning any address is wrong.

The correct way to use string is in your above example is:

#include <stdio.h>
#include <string.h>
int main()
{
    char str[] = "hello";
    char *pstr = str;
    printf("str = %s and pstr = %s\n", str, pstr);
    return 0;
}

or

char *p = NULL;
p = malloc(6);
if(p)
 strcpy(p,"hello");
printf("p = %s\n", p);
IrAM
  • 1,720
  • 5
  • 18
-1

I love this one!

Put the first example in a function. I bet that return following strcpy(&b, a); will crash you with a stack backtrace that will be useless. In that strcpy call you told it to copy string to address of variable b. But b is a local variable, so on stack. Address of it would also be on stack. By writing more than the size of b (which is 4 or 8 bytes, depending whether you are running 32 or 64 bit environment) you start overwriting other contents of the stack, eventually spoiling return address. When you exit your function (that's why I said to put it in a function) CPU reads return address from stack and jumps to it. But you spoiled it so it will try to jump at the new location, resulting in either segment fault or illegal instruction. Please, replace "hello" with something longer like "wellcome in hell!" (18+1 byes) and see what happens.

Executing printf("%s", &b) of course works, because with strcpy(&b, a); you copied string to stack. It will only crash when you get out of the function where all this is taking place.

I am sure that by now you already understand why the third piece of code, just as faulty as the first and second, works.

TCvD
  • 600
  • 2
  • 8