-3

I have a few questions regarding the code below.

  1. If I have a pointer of some type, what does it mean to use array indexing with it? in this example, what does ptr[3] stand for (ptr is a pointer of some type)?
  2. The output of the program is supposed to be to be or not to be (Hamlet) but I am not sure why, my problem is with the line (&ptr2)[3] = str, I don't understand how does this line changes the third element of the ptr1 array.

    int main()
    {
     char str[] = "hmmmm...";
     const char *const ptr1[] = {"to be", "or not to be", "that is the question"};
     char *ptr2 = "that is the question";
    
     (&ptr2)[3] = str;
    
     strcpy(str, "(Hamlet)");
     for (int i = 0; i < sizeof(ptr1) / sizeof(*ptr1); ++i)
     {
        printf("%s ", ptr1[i]);
     }
     return 0;
    }
    

Using this visualizer, we can see that ptr1 will point to str, I just don't understand why that happens.

Help appreciated.

rishat
  • 8,206
  • 4
  • 44
  • 69
user574362
  • 67
  • 1
  • 7
  • It might be helpful to know that the syntax `ptr[3]` is exactly the same as `*(ptr + 3)`. – 0x5453 Feb 22 '19 at 21:27
  • 2
    You should read a tutorial about arrays and pointers. – klutt Feb 22 '19 at 21:28
  • `ptr[3]` will access the 4th element of your array by adding `3*sizeof(datatype)` to the pointers base address and dereferencing it (note the first element is always `0`, not `1`). – Nidhoegger Feb 22 '19 at 21:30
  • @0x5453 this is only true if the type of the array is a type that is 1 byte in size (e.g. `char`), it wont apply to e.g. `int` (if you are using something else than an 8bit CPU) – Nidhoegger Feb 22 '19 at 21:31
  • This [duplicates the code in yesterday’s question](https://stackoverflow.com/questions/54810045/pointers-address-location) although this user asks different questions. – Eric Postpischil Feb 22 '19 at 21:47
  • @Nidhoegger The behavior does technically depend on the underlying type, but the type does not have to be 1 byte. Adding to a pointer takes the size of the pointed-to object into account, e.g. If `ptr` points to address `N`, then `ptr + x` points to address `N + (x * sizeof(*ptr))`. (Again, the behavior is exactly the same as the subscript operator.) – 0x5453 Feb 22 '19 at 22:29
  • @0x5453 only if the type is known. does not apply to `void *` – Nidhoegger Feb 23 '19 at 14:23

1 Answers1

2

If I have a pointer of some type, what does it mean to use array indexing with it? in this example, what does ptr[3] stand for (ptr is a pointer of some type)?

In C, a[i] is syntactic sugar for *(a + i). This is valid syntax for pointers, even if they aren't pointing to an array.

The output of the program is supposed to be to be or not to be (Hamlet) but I am not sure why, my problem is with the line (&ptr2)[3] = str, I don't understand how does this line changes the third element of the ptr1 array.

The line (&ptr2)[3] doesn't change anything in str1. It tries to access an unknown memory location.

If you were told that the output of this program is supposed to be "to be or not to be (Hamlet)", you were told wrong.

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
  • `(&ptr2)[3]` will dereference ptr2 (so it will be a `char **`, a pointer to the pointers memory) and write to that. It will most likely write to a random location (where the address is stored in memory) and corrupt `ptr2`. – Nidhoegger Feb 22 '19 at 21:33
  • @user574362 That still doesn't mean it's not undefined behavior. – Govind Parmar Feb 22 '19 at 21:36
  • @Nidhoegger why does it become char ** – user574362 Feb 22 '19 at 21:37
  • @user574362 as `ptr2` is of type `char *`, using the `&` operator will get the address of the `char *` which is of type `char **` (pointer to the pointer). As `ptr2` is also stored in memory (and contains the address to the first element` you can have a pointer to that address as well. – Nidhoegger Feb 22 '19 at 21:39
  • Does undefined behavior vary from different executions of the code? because at first I expected an undefined behavior but it kept printing the same string. – user574362 Feb 22 '19 at 21:39
  • @user574362 Read the [Wikipedia article](https://en.wikipedia.org/wiki/Undefined_behavior) on undefined behavior – Govind Parmar Feb 22 '19 at 21:40
  • @user574362 UB means that the behavior is undefined. That means that there are NO guarantees WHATSOEVER for ANYTHING. – klutt Feb 22 '19 at 21:42
  • @Broman: “WHATSOEVER” is incorrect. If you are using “undefined” with its meaning in the C standard, then all it means is that the C standard imposes no requirements. It does not extend beyond that. The only power of the C standard, or other specifications, is to define or withhold definition. They are unable to license violations of other documents or of laws of nature, mathematics, or humans. – Eric Postpischil Feb 23 '19 at 00:02
  • 1
    @EricPostpischil Forgive me, but is this a serious comment or just humorous? – klutt Feb 23 '19 at 00:04
  • @Broman: Unfortunately people are promoting statements such as yours in Stack Overflow to the detriment of learning. There is a propagation of notions that undefined behavior is incomprehensible and unanalyzable, that the behavior of a program whose behavior is not defined by the C standard cannot be analyzed and hence cannot be debugged. But that is not true. The behavior of a faulty program, including its output, traps, and memory dump, may contain clues that, interacting with the designs of compilers and more, aid diagnosis. There are patterns and reasons present in “undefined” behavior. – Eric Postpischil Feb 23 '19 at 00:08
  • 1
    @EricPostpischil Ok. Well, it was not my intention to imply that it cannot be debugged or analyzed, because it's simply not true. But there is a difference in "pattern" and "guarantee". – klutt Feb 23 '19 at 00:13
  • @Broman: But there are guarantees. The computer should not blow up; there are safety standards for consumer devices. The operating system should not crash; it is supposed to protect against that. The hardware should not be damaged by a software error. Just because the C standard does not define the behavior does not mean that other things do not apply—operating system specifications, hardware specifications, consumer law, laws of physics. A simple statement that the C standard does not define the behavior is true. A statement that there are no guarantees ”WHATSOEVER” is false. – Eric Postpischil Feb 23 '19 at 00:18
  • 1
    @EricPostpischil I'm pretty confident that the average SO user understands that no C program (or in any language) can break the laws of physics. – klutt Feb 23 '19 at 00:28
  • @EricPostpischil I mean, if you're going as far as to laws of physics, then you cannot, for example, guarantee that a particular implementation of bubble sort will work because someone could break the computer with a sledgehammer before the code has finnished running. It can also fail, because the operating system may accidentally corrupt the memory it is working with. Or maybe just terminate the program because a user requested it. But I don't think it is any point in listing all these cases when we say that a particular implementation of bubble sort will work correctly for all inputs. – klutt Feb 23 '19 at 00:51
  • @Broman: They may understand that a C program will not break the laws of physics, but they do not understand the intricacies of compilers, debuggers, and other tools. We should stop telling them that undefined behavior is a dark mystery. People have asked perfectly valid questions (not necessarily here) about **why** some particular behavior and been turned away from knowledge with a statement that the behavior is undefined when in fact there is a perfectly sensible explanation of why their particular observations were caused by how compilers operate. – Eric Postpischil Feb 23 '19 at 01:15
  • @Broman: In other words, the behavior they saw was not defined by the C standard, but **it was illuminating about how compilers work**. Stack Overflow has repeatedly stomped on opportunities to teach. Anyway, regardless of your opinion about the value of this information, the fact remains that the statement that the behavior is not defined by the C standard is **true**, and the statement that there is no guarantee “WHATSOEVER” is **false**. If the fact that a statement is false is not sufficient reason for you to disclaim and avoid it, that is a problem. – Eric Postpischil Feb 23 '19 at 01:17
  • @EricPostpischil Well, you do have some valid points but I think you're overreacting. Let's agree to disagree. – klutt Feb 23 '19 at 15:06
  • @Broman: No, the statement is false, and I will not agree otherwise. – Eric Postpischil Feb 23 '19 at 15:39
  • 1
    @EricPostpischil I wasn't referring to the logical truth value in the statement, but how much it really matters in practice. We say things that are not 100% correct everyday. Sometimes it matters and sometimes it does not. Sure, I could add the suffix "... according to the C standard" when I say that you don't have any guarantees, but I'm not sure that that will make things very much clearer to people. – klutt Feb 23 '19 at 20:52