Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

85%
+10 −0
Q&A Is it undefined behaviour to just make a pointer point outside boundaries of an array without dereferencing it?

Yes, the second line invokes undefined behavior. First of all, according to C17 6.5.2.1 regarding array subscripting, an expression E1[E2] is just "syntactic sugar" for *((E1)+(E2))). So what appli...

posted 4y ago by Lundin‭  ·  edited 4y ago by Lundin‭

Answer
#6: Post edited by user avatar Lundin‭ · 2020-08-21T13:13:06Z (about 4 years ago)
Changes to reflect an edit of the question.
  • Yes, the second line invokes undefined behavior.
  • First of all, according to C17 6.5.2.1 regarding array subscripting, an expression `E1[E2]` is just "syntactic sugar" for `*((E1)+(E2)))`. So what applies here is actually the binary + operator. More info regarding why `[]` is actually never used with an array operand [here](https://stackoverflow.com/questions/55747822/do-pointers-support-array-style-indexing).
  • (The code `char *ptr = arr[-1];` isn't correct C. That's another story, so I'm assuming this is a typo and that the intention was `char *ptr = &arr[-1];`)
  • So your example is equivalent to `char *ptr = *((arr) + (-1));`, where `arr` "decays" into a pointer to the first element. The `arr` operand ends up as a pointer type and the `-1` operand is an integer type.
  • C17 6.5.6/8 then provides the following text for additive operators:
  • > When an expression that has integer type is added to or subtracted from a pointer, the
  • result has the type of the pointer operand. /--/
  • > If both the pointer
  • operand and the result point to elements of the same array object, or one past the last
  • element of the array object, the evaluation shall not produce an overflow; otherwise, the
  • behavior is undefined.
  • In this case, the result does not point inside `arr` so "otherwise, the behavior is undefined".
  • That is, the evaluation of the + operator is what first causes undefined behavior, before the de-referencing.
  • ---
  • We can demonstrate this UB with gcc x86 -O3 by first compiling:
  • int arr[3] = {1,2,3};
  • printf("%d\n", arr[0]);
  • which disassembles into
  • mov edi, offset .L.str
  • mov esi, 1
  • That is, as part of some calling convention ESI gets directly loaded with the value 1 , equivalent to what would have been stored in arr[0] if the array got allocated. If I change this to `printf("%d\n", arr[-1]);`, the instruction for setting up ESI is simply removed from the disassembly and I suppose the program prints whatever garbage value that happened to be stored inside ESI. The compiler doesn't even attempt to de-reference the variable by fetching a value from the stack corresponding to memory address `arr - 1`.
  • Yes, the second line invokes undefined behavior.
  • First of all, according to C17 6.5.2.1 regarding array subscripting, an expression `E1[E2]` is just "syntactic sugar" for `*((E1)+(E2)))`. So what applies here is actually the binary + operator. More info regarding why `[]` is actually never used with an array operand [here](https://stackoverflow.com/questions/55747822/do-pointers-support-array-style-indexing).
  • So your example is equivalent to `char *ptr = &*((arr) + (-1));`, where `arr` "decays" into a pointer to the first element. The `arr` operand ends up as a pointer type and the `-1` operand is an integer type.
  • C17 6.5.6/8 then provides the following text for additive operators:
  • > When an expression that has integer type is added to or subtracted from a pointer, the
  • result has the type of the pointer operand. /--/
  • > If both the pointer
  • operand and the result point to elements of the same array object, or one past the last
  • element of the array object, the evaluation shall not produce an overflow; otherwise, the
  • behavior is undefined.
  • In this case, the result does not point inside `arr` so "otherwise, the behavior is undefined".
  • That is, the evaluation of the + operator is what first causes undefined behavior, before the de-referencing.
  • ---
  • We can demonstrate this UB with gcc x86 -O3 by first compiling:
  • int arr[3] = {1,2,3};
  • printf("%d\n", arr[0]);
  • which disassembles into
  • mov edi, offset .L.str
  • mov esi, 1
  • That is, as part of some calling convention ESI gets directly loaded with the value 1 , equivalent to what would have been stored in arr[0] if the array got allocated. If I change this to `printf("%d\n", arr[-1]);`, the instruction for setting up ESI is simply removed from the disassembly and I suppose the program prints whatever garbage value that happened to be stored inside ESI. The compiler doesn't even attempt to de-reference the variable by fetching a value from the stack corresponding to memory address `arr - 1`.
#5: Post edited by user avatar Lundin‭ · 2020-08-18T06:28:56Z (about 4 years ago)
  • Yes, the second line invokes undefined behavior.
  • First of all, according to C17 6.5.2.1 regarding array subscripting, an expression `E1[E2]` is just "syntactic sugar" for `*((E1)+(E2)))`. So what applies here is actually the binary + operator. More info regarding why `[]` is actually never used with an array operand [here](https://stackoverflow.com/questions/55747822/do-pointers-support-array-style-indexing).
  • So your example is equivalent to `char *ptr = *((arr) + (-1));`, where `arr` "decays" into a pointer to the first element. The `arr` operand ends up as a pointer type and the `-1` operand is an integer type.
  • C17 6.5.6/8 then provides the following text for additive operators:
  • > When an expression that has integer type is added to or subtracted from a pointer, the
  • result has the type of the pointer operand. /--/
  • > If both the pointer
  • operand and the result point to elements of the same array object, or one past the last
  • element of the array object, the evaluation shall not produce an overflow; otherwise, the
  • behavior is undefined.
  • In this case, the result does not point inside `arr` so "otherwise, the behavior is undefined".
  • That is, the evaluation of the + operator is what first causes undefined behavior, before the de-referencing.
  • ---
  • We can demonstrate this UB with gcc x86 -O3 by first compiling:
  • int arr[3] = {1,2,3};
  • printf("%d\n", arr[0]);
  • which disassembles into
  • mov edi, offset .L.str
  • mov esi, 1
  • That is, as part of some calling convention ESI gets directly loaded with the value 1 , equivalent to what would have been stored in arr[0] if the array got allocated. If I change this to `printf("%d\n", arr[-1]);`, the instruction for setting up ESI is simply removed from the disassembly and I suppose the program prints whatever garbage value that happened to be stored inside ESI. The compiler doesn't even attempt to de-reference the variable by fetching a value from the stack corresponding to memory address `arr - 1`.
  • Yes, the second line invokes undefined behavior.
  • First of all, according to C17 6.5.2.1 regarding array subscripting, an expression `E1[E2]` is just "syntactic sugar" for `*((E1)+(E2)))`. So what applies here is actually the binary + operator. More info regarding why `[]` is actually never used with an array operand [here](https://stackoverflow.com/questions/55747822/do-pointers-support-array-style-indexing).
  • (The code `char *ptr = arr[-1];` isn't correct C. That's another story, so I'm assuming this is a typo and that the intention was `char *ptr = &arr[-1];`)
  • So your example is equivalent to `char *ptr = *((arr) + (-1));`, where `arr` "decays" into a pointer to the first element. The `arr` operand ends up as a pointer type and the `-1` operand is an integer type.
  • C17 6.5.6/8 then provides the following text for additive operators:
  • > When an expression that has integer type is added to or subtracted from a pointer, the
  • result has the type of the pointer operand. /--/
  • > If both the pointer
  • operand and the result point to elements of the same array object, or one past the last
  • element of the array object, the evaluation shall not produce an overflow; otherwise, the
  • behavior is undefined.
  • In this case, the result does not point inside `arr` so "otherwise, the behavior is undefined".
  • That is, the evaluation of the + operator is what first causes undefined behavior, before the de-referencing.
  • ---
  • We can demonstrate this UB with gcc x86 -O3 by first compiling:
  • int arr[3] = {1,2,3};
  • printf("%d\n", arr[0]);
  • which disassembles into
  • mov edi, offset .L.str
  • mov esi, 1
  • That is, as part of some calling convention ESI gets directly loaded with the value 1 , equivalent to what would have been stored in arr[0] if the array got allocated. If I change this to `printf("%d\n", arr[-1]);`, the instruction for setting up ESI is simply removed from the disassembly and I suppose the program prints whatever garbage value that happened to be stored inside ESI. The compiler doesn't even attempt to de-reference the variable by fetching a value from the stack corresponding to memory address `arr - 1`.
#4: Post edited by user avatar Lundin‭ · 2020-08-11T13:17:41Z (about 4 years ago)
  • Yes, the second line invokes undefined behavior.
  • First of all, according to C17 6.5.2.1 regarding array subscripting, an expression `E1[E2]` is just "syntactic sugar" for `*((E1)+(E2)))`. So what applies here is actually the binary + operator. More info regarding why `[]` is actually never used with an array operand [here](https://stackoverflow.com/questions/55747822/do-pointers-support-array-style-indexing).
  • So your example is equivalent to `char *ptr = *((arr) + (-1));`, where `arr` "decays" into a pointer to the first element. The `arr` operand ends up as a pointer type and the `-1` operand is an integer type.
  • C17 6.5.6/8 then provides the following text for additive operators:
  • > When an expression that has integer type is added to or subtracted from a pointer, the
  • result has the type of the pointer operand. /--/
  • > If both the pointer
  • operand and the result point to elements of the same array object, or one past the last
  • element of the array object, the evaluation shall not produce an overflow; otherwise, the
  • behavior is undefined.
  • In this case, the result does not point inside `arr` so "otherwise, the behavior is undefined".
  • That is, the evaluation of the + operator is what first causes undefined behavior, before the de-referencing.
  • ---
  • We can demonstrate this UB with gcc x86 -O3 by first compiling:
  • int arr[3] = {1,2,3};
  • printf("%d\n", arr[0]);
  • which disassembles into
  • mov edi, offset .L.str
  • mov esi, 1
  • That is, as part of some calling convention ESI gets directly loaded with the value 1 from arr[0]. If I change this to `printf("%d
  • ", arr[-1]);`, the instruction for setting up ESI is simply removed from the disassembly and I suppose the program prints whatever garbage value that happened to be stored inside ESI. The compiler doesn't even attempt to de-reference the variable by fetching a value from the stack corresponding to memory address `arr - 1`.
  • Yes, the second line invokes undefined behavior.
  • First of all, according to C17 6.5.2.1 regarding array subscripting, an expression `E1[E2]` is just "syntactic sugar" for `*((E1)+(E2)))`. So what applies here is actually the binary + operator. More info regarding why `[]` is actually never used with an array operand [here](https://stackoverflow.com/questions/55747822/do-pointers-support-array-style-indexing).
  • So your example is equivalent to `char *ptr = *((arr) + (-1));`, where `arr` "decays" into a pointer to the first element. The `arr` operand ends up as a pointer type and the `-1` operand is an integer type.
  • C17 6.5.6/8 then provides the following text for additive operators:
  • > When an expression that has integer type is added to or subtracted from a pointer, the
  • result has the type of the pointer operand. /--/
  • > If both the pointer
  • operand and the result point to elements of the same array object, or one past the last
  • element of the array object, the evaluation shall not produce an overflow; otherwise, the
  • behavior is undefined.
  • In this case, the result does not point inside `arr` so "otherwise, the behavior is undefined".
  • That is, the evaluation of the + operator is what first causes undefined behavior, before the de-referencing.
  • ---
  • We can demonstrate this UB with gcc x86 -O3 by first compiling:
  • int arr[3] = {1,2,3};
  • printf("%d\n", arr[0]);
  • which disassembles into
  • mov edi, offset .L.str
  • mov esi, 1
  • That is, as part of some calling convention ESI gets directly loaded with the value 1 , equivalent to what would have been stored in arr[0] if the array got allocated. If I change this to `printf("%d
  • ", arr[-1]);`, the instruction for setting up ESI is simply removed from the disassembly and I suppose the program prints whatever garbage value that happened to be stored inside ESI. The compiler doesn't even attempt to de-reference the variable by fetching a value from the stack corresponding to memory address `arr - 1`.
#3: Post edited by user avatar Lundin‭ · 2020-08-11T13:16:48Z (about 4 years ago)
  • Yes, the second line invokes undefined behavior.
  • First of all, according to C17 6.5.2.1 regarding array subscripting, an expression `E1[E2]` is just "syntactic sugar" for `*((E1)+(E2)))`. So what applies here is actually the binary + operator. More info regarding why `[]` is actually never used with an array operand [here](https://stackoverflow.com/questions/55747822/do-pointers-support-array-style-indexing).
  • So your example is equivalent to `char *ptr = *((arr) + (-1));`, where `arr` "decays" into a pointer to the first element. The `arr` operand ends up as a pointer type and the `-1` operand is an integer type.
  • C17 6.5.6/8 then provides the following text for additive operators:
  • > When an expression that has integer type is added to or subtracted from a pointer, the
  • result has the type of the pointer operand. /--/
  • > If both the pointer
  • operand and the result point to elements of the same array object, or one past the last
  • element of the array object, the evaluation shall not produce an overflow; otherwise, the
  • behavior is undefined.
  • In this case, the result does not point inside `arr` so "otherwise, the behavior is undefined".
  • That is, the evaluation of the + operator is what first causes undefined behavior, before the de-referencing.
  • ---
  • We can demonstrate this UB with gcc x86 -O3 by first compiling:
  • int arr[3] = {1,2,3};
  • printf("%d\n", arr[0]);
  • which disassembles into
  • mov edi, offset .L.str
  • mov esi, 1
  • That is, as part of some calling convention ESI gets directly loaded with the value 1 from arr[0]. If I change this to `printf("%d
  • ", arr[-1]);`, the instruction for setting up ESI is simply removed from the disassembly and I suppose the program prints whatever garbage value that happened to be stored inside ESI. The compiler doesn't even attempt to de-reference the variable by fetching a value from the stack corresponding to memory address `arr - 1`. The array was never de-referenced since the whole array got optimized away.
  • Yes, the second line invokes undefined behavior.
  • First of all, according to C17 6.5.2.1 regarding array subscripting, an expression `E1[E2]` is just "syntactic sugar" for `*((E1)+(E2)))`. So what applies here is actually the binary + operator. More info regarding why `[]` is actually never used with an array operand [here](https://stackoverflow.com/questions/55747822/do-pointers-support-array-style-indexing).
  • So your example is equivalent to `char *ptr = *((arr) + (-1));`, where `arr` "decays" into a pointer to the first element. The `arr` operand ends up as a pointer type and the `-1` operand is an integer type.
  • C17 6.5.6/8 then provides the following text for additive operators:
  • > When an expression that has integer type is added to or subtracted from a pointer, the
  • result has the type of the pointer operand. /--/
  • > If both the pointer
  • operand and the result point to elements of the same array object, or one past the last
  • element of the array object, the evaluation shall not produce an overflow; otherwise, the
  • behavior is undefined.
  • In this case, the result does not point inside `arr` so "otherwise, the behavior is undefined".
  • That is, the evaluation of the + operator is what first causes undefined behavior, before the de-referencing.
  • ---
  • We can demonstrate this UB with gcc x86 -O3 by first compiling:
  • int arr[3] = {1,2,3};
  • printf("%d\n", arr[0]);
  • which disassembles into
  • mov edi, offset .L.str
  • mov esi, 1
  • That is, as part of some calling convention ESI gets directly loaded with the value 1 from arr[0]. If I change this to `printf("%d
  • ", arr[-1]);`, the instruction for setting up ESI is simply removed from the disassembly and I suppose the program prints whatever garbage value that happened to be stored inside ESI. The compiler doesn't even attempt to de-reference the variable by fetching a value from the stack corresponding to memory address `arr - 1`.
#2: Post edited by user avatar Lundin‭ · 2020-08-11T13:16:24Z (about 4 years ago)
  • Yes, the second line invokes undefined behavior.
  • First of all, according to C17 6.5.2.1 regarding array subscripting, an expression `E1[E2]` is just "syntactic sugar" for `*((E1)+(E2)))`. So what applies here is actually the binary + operator. More info regarding why `[]` is actually never used with an array operand [here](https://stackoverflow.com/questions/55747822/do-pointers-support-array-style-indexing).
  • So your example is equivalent to `char *ptr = *((arr) + (-1));`, where `arr` "decays" into a pointer to the first element. The `arr` operand ends up as a pointer type and the `-1` operand is an integer type.
  • C17 6.5.6/8 then provides the following text for additive operators:
  • > When an expression that has integer type is added to or subtracted from a pointer, the
  • result has the type of the pointer operand. /--/
  • > If both the pointer
  • operand and the result point to elements of the same array object, or one past the last
  • element of the array object, the evaluation shall not produce an overflow; otherwise, the
  • behavior is undefined.
  • In this case, the result does not point inside `arr` so "otherwise, the behavior is undefined".
  • That is, the evaluation of the + operator is what first causes undefined behavior, before the de-referencing.
  • ---
  • We can demonstrate this UB with gcc x86 -O3 by first compiling:
  • int arr[3] = {1,2,3};
  • printf("%d\n", arr[0]);
  • which disassembles into
  • mov edi, offset .L.str
  • mov esi, 1
  • That is, as part of some calling convention ESI gets directly loaded with the value 1 from arr[0]. If I change this to `printf("%d
  • ", arr[-1]);`, the instruction for setting up ESI is simply removed from the disassembly and I suppose the program prints whatever garbage value that happened to be stored inside ESI. The compiler doesn't even attempt to fetch a value from the stack corresponding to memory address `arr - 1`.
  • Yes, the second line invokes undefined behavior.
  • First of all, according to C17 6.5.2.1 regarding array subscripting, an expression `E1[E2]` is just "syntactic sugar" for `*((E1)+(E2)))`. So what applies here is actually the binary + operator. More info regarding why `[]` is actually never used with an array operand [here](https://stackoverflow.com/questions/55747822/do-pointers-support-array-style-indexing).
  • So your example is equivalent to `char *ptr = *((arr) + (-1));`, where `arr` "decays" into a pointer to the first element. The `arr` operand ends up as a pointer type and the `-1` operand is an integer type.
  • C17 6.5.6/8 then provides the following text for additive operators:
  • > When an expression that has integer type is added to or subtracted from a pointer, the
  • result has the type of the pointer operand. /--/
  • > If both the pointer
  • operand and the result point to elements of the same array object, or one past the last
  • element of the array object, the evaluation shall not produce an overflow; otherwise, the
  • behavior is undefined.
  • In this case, the result does not point inside `arr` so "otherwise, the behavior is undefined".
  • That is, the evaluation of the + operator is what first causes undefined behavior, before the de-referencing.
  • ---
  • We can demonstrate this UB with gcc x86 -O3 by first compiling:
  • int arr[3] = {1,2,3};
  • printf("%d\n", arr[0]);
  • which disassembles into
  • mov edi, offset .L.str
  • mov esi, 1
  • That is, as part of some calling convention ESI gets directly loaded with the value 1 from arr[0]. If I change this to `printf("%d
  • ", arr[-1]);`, the instruction for setting up ESI is simply removed from the disassembly and I suppose the program prints whatever garbage value that happened to be stored inside ESI. The compiler doesn't even attempt to de-reference the variable by fetching a value from the stack corresponding to memory address `arr - 1`. The array was never de-referenced since the whole array got optimized away.
#1: Initial revision by user avatar Lundin‭ · 2020-08-11T13:08:40Z (about 4 years ago)
Yes, the second line invokes undefined behavior.

First of all, according to C17 6.5.2.1 regarding array subscripting, an expression `E1[E2]` is just "syntactic sugar" for `*((E1)+(E2)))`. So what applies here is actually the binary + operator. More info regarding why `[]` is actually never used with an array operand [here](https://stackoverflow.com/questions/55747822/do-pointers-support-array-style-indexing).

So your example is equivalent to `char *ptr = *((arr) + (-1));`, where `arr` "decays" into a pointer to the first element. The `arr` operand ends up as a pointer type and the `-1` operand is an integer type.

C17 6.5.6/8 then provides the following text for additive operators:

> When an expression that has integer type is added to or subtracted from a pointer, the
result has the type of the pointer operand. /--/  
> If both the pointer
operand and the result point to elements of the same array object, or one past the last
element of the array object, the evaluation shall not produce an overflow; otherwise, the
behavior is undefined.

In this case, the result does not point inside `arr` so "otherwise, the behavior is undefined".

That is, the evaluation of the + operator is what first causes undefined behavior, before the de-referencing.

---

We can demonstrate this UB with gcc x86 -O3 by first compiling:

    int arr[3] = {1,2,3};
    printf("%d\n", arr[0]);

which disassembles into 

        mov     edi, offset .L.str
        mov     esi, 1

That is, as part of some calling convention ESI gets directly loaded with the value 1 from arr[0]. If I change this to `printf("%d\n", arr[-1]);`, the instruction for setting up ESI is simply removed from the disassembly and I suppose the program prints whatever garbage value that happened to be stored inside ESI. The compiler doesn't even attempt to fetch a value from the stack corresponding to memory address `arr - 1`.