-1

Is there any way I can create two variables that point to the same memory location, so that I can read same memory as int, float, char, any way I like?

I want something like this, only without pointer to f, so that I do not have to dereference every time I read/write to f.

char myArray[100];
float* f = (float *)&myArray[10];

I want to closest thing to C++'s reference in C.

I hope the question makes sense.

Edit: I read stream (4 Kb worth) of bytes from flash memory. This stream contains shorts, ints and floats. I know the locations of these ints and floats in the array. And I want to read/write the aforementioned ints and floats like they are ordinary variables.

Hassan
  • 870
  • 13
  • 25
  • Are you looking for the idea of a `union`? Also, `C++` has references. Anyways, keep in mind that this is dangerous; if you put a `float` in some region of memory, then reread and modify it as if it were an `int`, then read it as a `float` again, then I believe compiler is perfectly within its rights to completely ignore the changes you made. –  May 31 '15 at 18:05
  • 1
    *"I know the locations of these ints and floats in the array."* So why don't you declare a (packed?) `struct` that matches the data? – Weather Vane May 31 '15 at 18:38
  • @WeatherVane, could I be able to read the raw bytes into the struct? – Hassan May 31 '15 at 18:43
  • Can you give us an example of the layout of your stream? – byako May 31 '15 at 18:46
  • @haxan7 my answer shows an example reading from binary file. – Weather Vane May 31 '15 at 18:53

2 Answers2

2

This example reads the data into a predefined struct, packed (if necessary). Beware of endian-ness! And of data types: an int on your target might be short on you PC.

#include<stdio.h>

#pragma pack(push, 1)
struct mydata {
    int version;
    char title[16];
    float reading[8];
} mydata;

#pragma pack(pop)

int main(void)
{
    FILE *fp;
    struct mydata data = {0};
    fp = fopen("mydata.bin", "rb");

    if (1 != fread(&data, sizeof(data), 1, fp))
        { // error
        }

    printf("Version = %d\n", data.version);

    fclose(fp);
    return 0;
}
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • typo: fread(&data, sizeof(data), 1, fp) should be fread(&data, 1, sizeof(data), fp) – Hassan May 31 '15 at 20:14
  • @haxan7 nope. I am checking that 1 record of that size is read. It *could* be the other way round, but you would then have to check `if (sizeof(data) != fread(&data, 1, sizeof(data), fp))`. Please look up `fread` https://msdn.microsoft.com/en-us/library/kt0etdcs.aspx – Weather Vane May 31 '15 at 20:22
  • this is where I go for documentation http://www.cplusplus.com/reference/cstdio/fread/ – Hassan May 31 '15 at 20:50
  • you have been most helpful, do I need to be worried about this: http://stackoverflow.com/questions/3638317/why-does-a-struct-consisting-of-a-char-short-and-char-in-that-order-when-co ? – Hassan May 31 '15 at 21:04
  • Yes, that and endian-ness as I commented. – Weather Vane May 31 '15 at 21:10
1

This is why unions exist.

union u {
  char c[4];
  float f;
  int i; // assuming sizeof(int) = 4 for this example
};

union u cf;
cf.f = 1.;
int i = cf.i;

Beware that the last line is actually incorrect per the C standard, because of strict aliasing. See for example What is the strict aliasing rule? You should always access the binary representation through a char l-value.

Community
  • 1
  • 1
byako
  • 3,372
  • 2
  • 21
  • 36
  • I think you misunderstood the question, I have updated my question for clarification. – Hassan May 31 '15 at 18:31
  • I'm still not sure I understand what you mean. It seems you want to read through the stream using a pointer that you increment? If so, you could declare a pointer to `union u`. However, this will require some care before performing the incrementation. I think the suggestion of @Weather Vane is actually simpler. – byako May 31 '15 at 18:46