1

I have the following struct:

typedef struct ${
 char author[27];
 char iso[2];
 int nrVolumes;
 TVolume* volume; //this is another struct
}TAuthor;

I need a function to return a pointer to a TAuthor. This function will be passing an int-nrVol- and it has to return a pointer to TAuthor which has nrVolumes field = nrVol. I have made to functions.

TAuthor* aloc1(int nrVol){
  TAuthor* new = (TAuthor*)malloc(sizeof(TAuthor));
  new->nrVolumes = nrVol;
  return new;
}

This one runs as expected.

TAuthor* aloc2(int nrVol){
  char* new = malloc(sizeof(TAuthor));
  (TAuthor*)new->nrVolumes = nrVol;
  return (TAuthor*)new;
}

At compilation "aloc2" gives me this error : request for member 'nrVolumes' in something not a structure or union

Why doesn't my casting work ? Since "new" is just an array of bytes, I suppose that even by casting the compiler doesn't know which bytes are responsible for which field, but I am not sure of this

Ncs
  • 313
  • 1
  • 9

2 Answers2

2

You need to first typecast new to TAuthor and then point it to its member:

TAuthor* aloc2(int nrVol){
  char* new = malloc(sizeof(TAuthor));
  ((TAuthor*)new)->nrVolumes = nrVol;
  return (TAuthor*)new;
}
-1

Two bugs:

  • The -> operator has higher precedence than the cast operator.
  • You shouldn't cast from a char array to a struct, because that will invoke a strict aliasing bug. What is the strict aliasing rule?

Simply use the first version which is fine.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Thank you for the quick answer and useful link. So my supposition is not correct? – Ncs Feb 05 '18 at 11:14
  • @Ncs The problem with strict aliasing bugs is that when you allocate an array of `char`, then access that array through a pointer to another type, the compiler is free to assume that the array has not been accessed at all, and may optimize the code accordingly, leading to bugs. As a special case, you are however allowed to do the opposite: access a type of any kind through a character type pointer, to access individual bytes. – Lundin Feb 05 '18 at 11:39
  • There is no strict aliasing violation. The rule is about to the effective type of memory being read or written. Having a `char *` point to some memory , without reading or writing through it, does not change the effective type of the memory. Furthermore, writing to dynamically allocated space sets the effective type to whatever you are writing as; it's never a strict aliasing violation to write to dynamically allocated space. – M.M Feb 05 '18 at 12:20
  • @M.M 1) I'm assuming that the programmer's intention of the struct is to actually use it in the program. 2) By accessing the returned value from malloc by a character pointer, the effective type becomes that of the lvalue used for access, as per C11 6.5/6. – Lundin Feb 05 '18 at 12:43
  • @EricPostpischil And `new` is a character pointer. The real issue here is that the program may assume that the pointer is never used, so the OS never makes the actual call to allocate memory - some OS only do this at the point where the memory is actually accessed. In which case you would get very weird bugs when using the struct. – Lundin Feb 05 '18 at 12:49
  • @EricPostpischil That's just because there is an unintended precedence bug in the code. Casting the value of an uninitialized variable to a pointer, where the result is not a lvalue, then assign an integer to that, is just nonsense code. My point here is that even if that bug is fixed, the code is still fishy. – Lundin Feb 05 '18 at 12:57
  • @Lundin: Sorry, I just copied the OP’s code without fixing the precedence error. In `((TAuthor*)new)->nrVolumes = nrVol;`, the lvalue used to access the memory is `((TAuthor*)new)->nrVolumes`. The type of that is `int`. The fact that there is a character pointer inside the expression is irrelevant; it has no bearing on what the type of the lvalue used to access memory is. – Eric Postpischil Feb 05 '18 at 13:01
  • Seriously people, do you think we should teach beginners to do wild pointer casts between unrelated types? The whole point here is "do not do stupid stuff". Any discussion about the intricate details of "effective type" in the inner workings of chapter 6.5, is not going to help a beginner. But since you down-voted my answer, the beginner may now think it is less credible than the "go ahead and wildly cast away" answer. Yet another C beginner mislead, good job. – Lundin Feb 05 '18 at 13:02
  • @Lundin: It is fine to teach a beginner not to use overly complicated code. It is not fine to teach them a false rule. An error in your answer is an error in your answer. – Eric Postpischil Feb 05 '18 at 13:03
  • The discussion of effective type is not to help the OP. It is to help you. That is why it is the comments to your answer, not in an answer. We are not suggesting you explain to the OP about effective type. We are suggesting you not teach them an incorrect rule about aliasing. – Eric Postpischil Feb 05 '18 at 13:07
  • @Lundin Claiming a strict aliasing violation where there isn't one, is even more confusing IMO. In fact that entire topic has nothing whatsoever to do with OP's question – M.M Feb 06 '18 at 21:04
  • @M.M: Right you are. Thanks, I deleted my previous comment about that. – Eric Postpischil Feb 06 '18 at 21:49