0

I am preparing to take my c certification exam and one of the practice questions really has me stumped. I am hoping some c experts can help me understand this code (yes, I know this code is contrived, but that is what I am dealing with to pass this cert test):

#include <stdio.h> 
#include <stdlib.h>
int main(void) { 
    float *t = 1 + (float *) malloc(sizeof(float) * sizeof(float));
    t--;
    *t = 8.0;
    t[1] = *t / 4.0;
    t++;
    t[-1] = *t / 2.0;
    printf("%f\n",*t);
    free(--t);
    return 0; 
}

I am going to note down what I believe each line does and would verification/corrections.

1: Defines variable t which is a pointer to type float. Since I don't know how many types this system is running on, I don't know how to know what size of memory is being allocated. After the allocation, we add 1 which I think should move the pointer, but not sure

2: Moves the pointer back one?

3: Assigns the value 8.0 to the memory pointed to by t

4: Divides 8.0 (*t) by 4.0 and comes up with 2, but I don't understand what t[1]is in this case

5: Move the pointer? But to where since this is of type float *

6: Moves the pointer back 1 and assigns *t / 2.0 (couldn't figure out what *t is at this point)

7: prints out the value pointed to by t

8: frees the memory pointed to by --t

vitr
  • 6,766
  • 8
  • 30
  • 50
Adam
  • 21
  • 3
  • Not looking closely, the size `sizeof(float) * sizeof(float)` looks weird. Usually size calculation will be `(size of one element) * (number of elements)`. Also note that they say [you shouldn't cast the result of `malloc()` in C](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – MikeCAT Sep 15 '16 at 03:25
  • Ah, in this case the casting is required to get `+` operator work. – MikeCAT Sep 15 '16 at 03:26
  • And this code is potential undefined behavior. If `malloc()` returns `NULL` the program will behave in an unpredictable way. You may explain all the behavior but only if `malloc()` returns a valid pointer. – Iharob Al Asimi Sep 15 '16 at 03:27
  • I think you have to cast the result of malloc unless you are assigning it to a type of void * (which is what malloc returns). And yes, line 1 is just baffling on so many levels. This may just be one of the strangest test questions I have ever seen. – Adam Sep 15 '16 at 03:29
  • @iharob - Just to clarify, I would never write code like this, but I need to understand it so I don't get the wrong answer when taking the certification test. Let's assume that memory is correctly allocated. In that case, could you help me trace the rest of the program? Thanks much in advance. – Adam Sep 15 '16 at 03:31
  • @Adam, NO. The cast is to be able to do pointer arithmetic, because you can't do it with `void *`, you need the cast for the `1 +` as MikeCAT said. It's really strange. – Iharob Al Asimi Sep 15 '16 at 03:31
  • @Adam, I am afraid I can't. You should read about pointer arithmetics and how to dereference pointers in c, then you can understand this by yourself. You are not that far, just need some key concepts. I am going to vote to close this question as *too broad*. – Iharob Al Asimi Sep 15 '16 at 03:32
  • @iharob - I do understand pointer arithmetic when it comes to using it on arrays, but what exactly does it do for a pointer to a float? That is what I don't get. Maybe I should post a more specific question (after researching first) on what pointer arithmetic does when using a pointer to float. – Adam Sep 15 '16 at 03:34
  • This looks like a good tutorial on pointer arithmetic: https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/pointer.html. – R Sahu Sep 15 '16 at 03:34
  • @RSahu - That tutorial did actually help trigger an understanding! Just for posterity's sake, when adding 1 to a pointer it moves forward the number of bytes of the type defined. So, in this case, if we assume that sizeof(float) = 4 then the malloc creates a memory size of 16 bytes and when doing the 1 + moves the pointer forward 4 so we are pointing at 5th byte (2nd float in memory). I should be able to trace the rest of it with this understanding. Thanks much!! – Adam Sep 15 '16 at 03:41
  • @Adam, that's true and is the crux of pointer arithmetic in C and C++. – R Sahu Sep 15 '16 at 03:42

1 Answers1

1
// Allocate a number of floats in memory
// t points to the second allocated float due to "1 + ..."
float *t = 1 + (float *) malloc(sizeof(float) * sizeof(float));

// t now points to the first allocated float
t--;

// first allocated float is set to 8.0
*t = 8.0;

// second allocated float is set to 2.0 (i.e. 8.0/4.0)
// note: t[1] is the same as *(t + 1)
t[1] = *t / 4.0;

// t now points to the second allocated float
t++;

// first allocated float is set to 1.0 (i.e. 2.0/2.0)
// note: t[-1] is the same as *(t - 1)
t[-1] = *t / 2.0;

// Prints 2.0 as t still points to the second allocated float
printf("%f\n",*t);

// Decrement t, i.e. t points to first allocated float
// and free the memory
free(--t);

// End the program by returning from main
return 0; 
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • That about covers it. Just a personal style nit on comments, `/* stuff */` I generally find easier on the eye, but to each his own. – David C. Rankin Sep 15 '16 at 07:31
  • @DavidC.Rankin Using `/* */` for small single-line comments is bad practice, because it won't allow you to "comment-out" the whole code where the comment resides. I believe that "recursive comments", for example: `/* stuff /* things */ */`, is not allowed by any C standard. – Lundin Sep 22 '17 at 12:59
  • Umm... I get what you are saying, and understand the use of both single and multi-line comments, but I'm a bit confused where `/* stuff /* things */ */` relates to my comment? Not saying it doesn't, just saying I'm left scratching my head a bit regarding the intent of your comment. – David C. Rankin Sep 22 '17 at 13:06