1

I read the standard but still cannot be sure:

#include <stdio.h>
#include <string.h>

void repl(char *restrict ap){
    char *cp=strchr(ap,(int)'m');
    *cp='M';
}

int main(){
    char arr[] = "example";
    repl(arr);
    puts(arr);
    return 0;
}

In the function repl, I used strchr to get another pointer for modifying the object. I expect the result is the string with the first m replaced with M.

But could this be undefined behavior?

If yes, then what about using ap[cp-ap]='M'; instead of *cp='M';?

cshu
  • 5,654
  • 28
  • 44
  • Yes, but it doesn't indicate anything very much in this context. AFAICT, you need two pointer variables in an argument list for it to make a difference. I see nothing that would break the restrict in the code you show. – Jonathan Leffler Dec 27 '14 at 03:13
  • Literals such as `'m'` already have type `int`. So no need to cast them, and in any case, even if the types were different a cast is not a good idea, anyhow. – Jens Gustedt Dec 27 '14 at 10:25

3 Answers3

2

Aliasing rules allow to access any variable through its own type or by the character type (including its signed / unsigned variant). It means that *cp='M'; is specified behavior without any special precaution needed as *cp is of character type.

On a different subject you don't need to cast 'm' in (int)'m' as 'm' is already of type int in C.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • You are right, I just realized the literal is of type `int`. Thanks. Actually I asked the question because I worried about that maybe complier doesn't know the relation between `cp` and `ap` and simply believes that `"example"` is never modifed. – cshu Dec 27 '14 at 02:30
  • @ouah Are you saying that a char/unsigned char pointer is allowed to alias a restrict pointer ? (If so, what's the point of restrict on the arguments of strcpy() ?) – nos Dec 27 '14 at 02:34
  • 3
    @nos `restrict` is used in `strcpy` as a hint (for optimization purposes) to inform the compiler that the two pointers don't alias . C allows a `char *` to alias any other pointer. – ouah Dec 27 '14 at 02:51
  • @ouah 6.7.3-7 of c99 seems to say it's more than a hint... though I'm not able to decipher the actual definition in 6.7.3.1 – nos Dec 27 '14 at 03:10
0

It's not undefined behaviour, because the pointer cp is derived from the pointer variable ap.

How does the compiler know that cp is derived from ap? It doesn't have to know. First, whether the compiler knows or not doesn't change that the behaviour is defined or undefined. The rule isn't "if the compiler knows...", the rule is "if cp is derived from ap".

As long as the compiler cannot prove that cp wasn't derived from ap, it must provide the exact same semantics as if you hadn't used the restrict keyword.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • 1
    Can I be a little curious about how the compiler knows `cp` is derived from `ap` (rather than irrelevant source)? :) – cshu Dec 27 '14 at 02:37
0

I have the impression that you get the purpose of the restrict modifier wrong. It is a guarantee that the caller of the function has to provide, namely that the object isn't accessible through any other pointer and wouldn't be modified unexpectedly by using such another pointer. So the usage of restrict qualified pointers doesn't lead to UB.

In addition in your case you are passing such a pointer to a function. After that the compiler can't assume anymore that the pointer doesn't alias, e.g to a global variable or to the pointer that the function returns. (which it actually does)

To give you an example, it is not the function memcpy which has UB. But it would be your call to memcpy that hasn't defined behavior if the two pointers point to overlapping objects.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177