Thread: Is this undefined behavior in C99?

  1. #1
    Registered User
    Join Date
    Apr 2019
    Posts
    62

    Is this undefined behavior in C99?

    I'm reading elsewhere that adding more than one to this pointer is undefined behavior. And I know the code is a bit nonsense, it originates from an exam question and is just meant to demonstrate pointer arithmetic.

    Code:
    #include <stdio.h>
    
    int main() {
       float *p = (float *)50;
       p = p + 3;
       printf("%p", p);
    }

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,231
    The rule that you might be thinking of is the one about pointer arithmetic with respect to the elements of an array: in such a case the standard defines addition of an integer to a pointer such that the result points to an element of the array, or one past the end, otherwise the behaviour is undefined. But here you are arbitrarily obtaining a pointer from an integer value: it could well be that any arithmetic with such a pointer is technically undefined behaviour, just that certain implementations may permit it for their own use cases.

    So, the way I would interpret this in the context of an exam question is that the behaviour is undefined, but make reasonable assumptions about the implementation permitting it.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,489
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Apr 2019
    Posts
    62
    Ah, that's where it's from. I wrote it down in my notebook and couldn't find it again!

  5. #5
    Registered User
    Join Date
    Apr 2019
    Posts
    62
    Quote Originally Posted by laserlight View Post
    The rule that you might be thinking of is the one about pointer arithmetic with respect to the elements of an array: in such a case the standard defines addition of an integer to a pointer such that the result points to an element of the array, or one past the end, otherwise the behaviour is undefined. But here you are arbitrarily obtaining a pointer from an integer value: it could well be that any arithmetic with such a pointer is technically undefined behaviour, just that certain implementations may permit it for their own use cases.

    So, the way I would interpret this in the context of an exam question is that the behaviour is undefined, but make reasonable assumptions about the implementation permitting it.
    This is surprising, because I've seen code just like this many times in low level code. For example, you know the address of a group of hardware registers, or memory used by the BIOS, and you address it much like the code in this example. Is there a way to arbitrarily address an array in a fixed place in memory that is not undefined behavior? Say I have the address of an array of interrupt vectors, normally I'd say something like uint32_t *ivt = 0xdeadfood; and address it like *(ivt + 3) = 0xcafebeef; or ivt[3] = 0xcafebeef;. These are both undefined behavior?

    Since you can't define the address of an array in C, the only way I can think of doing it is to declare extern uint32_t ivt[32]; and give the address via the linker, outside of C.
    Last edited by gaxio; 01-15-2021 at 06:13 AM.

  6. #6
    Registered User
    Join Date
    Dec 2017
    Posts
    1,068
    You are misunderstanding what "undefined behavior" means. It doesn't mean that it won't work or will definitely blow up in every implementation of the language. It just means that the standard itself does not define any particular behavior, leaving it up to the implementation to either not handle the case at all and therefore allow anything at all to happen or to define it for it's own purposes.
    Philosophy is a battle against the bewitchment of our intelligence by means of language. - Wittgenstein

  7. #7
    Registered User
    Join Date
    Apr 2019
    Posts
    62
    I realize that, like I said I've seen code like this work many times on many platforms and compilers. I'm just asking how to do this without undefined behavior regardless of whether it works with the undefined behavior. Also, is this undefined behavior, or implementation-defined behavior? Because what you're describing is implementation-defined behavior, not undefined behavior.

  8. #8
    Registered User
    Join Date
    Dec 2017
    Posts
    1,068
    You have no idea what you are talking about. But since you are convinced that you do, there's no point in my continuing the discussion. Good luck with that.
    Philosophy is a battle against the bewitchment of our intelligence by means of language. - Wittgenstein

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,231
    Quote Originally Posted by gaxio
    This is surprising, because I've seen code just like this many times in low level code. For example, you know the address of a group of hardware registers, or memory used by the BIOS, and you address it much like the code in this example.
    That's what I had in mind when I wrote that "just that certain implementations may permit it for their own use cases".

    Quote Originally Posted by gaxio
    Say I have the address of an array of interrupt vectors, normally I'd say something like uint32_t *ivt = 0xdeadfood; and address it like *(ivt + 3) = 0xcafebeef; or ivt[3] = 0xcafebeef;. These are both undefined behavior?
    No, just assigning an arbitrary address without doing pointer arithmetic is implementation-defined, not undefined, behaviour:
    Quote Originally Posted by C99 Clause 6.3.2.3 Paragraph 5
    An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.
    (The "except as previously specified" of course refers to 0 as a null pointer constant.)

    Quote Originally Posted by gaxio
    Also, is this undefined behavior, or implementation-defined behavior? Because what you're describing is implementation-defined behavior, not undefined behavior.
    You are mistaken. john.c correctly stated a definition of "undefined behaviour" in post #6. If you want a refresher, here are the definitions of the terms from C99:
    implementation-defined behavior
    unspecified behavior where each implementation documents how the choice is made

    undefined behavior
    behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements

    unspecified behavior
    behavior where this International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance
    Notice that implementation-defined behaviour is a kind of unspecified behaviour, and that unspecified behaviour still involves definition of behaviour, just that the behaviour is not well defined in the sense that there is only one possibility; rather there are multiple possibilities, and unspecified versus implementation-defined is just a question of no need to document versus shall document. Whereas for undefined behaviour, notice the words "nonportable" and "Standard imposes no requirements". That's what you're looking at here.
    Last edited by laserlight; 01-15-2021 at 09:06 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Undefined behavior
    By atran in forum C Programming
    Replies: 3
    Last Post: 04-04-2015, 02:27 PM
  2. Undefined behavior
    By Ducky in forum C Programming
    Replies: 14
    Last Post: 11-17-2013, 07:10 AM
  3. Undefined behavior
    By jim mcnamara in forum C Programming
    Replies: 2
    Last Post: 02-18-2013, 11:14 PM
  4. Is x=x++; Undefined Behavior?
    By envec83 in forum C Programming
    Replies: 5
    Last Post: 10-04-2011, 01:27 AM
  5. Undefined behavior from VC6 to 2k5
    By m37h0d in forum C++ Programming
    Replies: 10
    Last Post: 06-22-2011, 07:56 PM

Tags for this Thread