1
struct Intx4 {
  int data[4];
};

Intx4 loadIntx4(void const *p) {
  auto up alignas(1) = (int const *)p; // Does this line correct? (compiled ok in clang)
  Intx4 r;
  for (int i = 0; i < 4; i++) r.data[i] = up[i];
  return r;
}

I also tried the followings, they all failed to compile in clang:

int const *up alignas(1) = (int const *)p;
auto up = (int const alignas(1) *)p;
wincmder
  • 61
  • 1
  • 3
  • 1
    why dont you just send in Intx4 ref? This is more C than C++, except alignas – Creris Aug 17 '15 at 12:49
  • I just want to known how to express reading an int from unaligned memory address. – wincmder Aug 17 '15 at 12:55
  • 1
    Beware, reading an int from an unaligned address will throw exception on some architectures (ARM), and is explicitely undefined behaviour in all versions of C++. – Serge Ballesta Aug 17 '15 at 13:00
  • @SergeBallesta: Since C++ only started to specify a memory model starting with C++11, I would question your statement about unaligned memory addresses causing undefined behavior. This is not even true in C++11. – IInspectable Aug 17 '15 at 13:02
  • @SergeBallesta Reference? I am highly skeptical. – Barry Aug 17 '15 at 13:02
  • I mean how to tell the compiler that I want to read an int from unaligned memory address, then the compiler will generate proper code to deal with the unaligned access. – wincmder Aug 17 '15 at 13:03
  • `alignas` applies to the variable itself, not its value. If you're on an architecture that supports unaligned reads and writes, your compiler should already be handling that behind the scenes. (Also, `memcpy(r.data, p, sizeof(r.data));`.) – molbdnilo Aug 17 '15 at 13:14
  • Why do not you want to use `int *up = (int const *)p;`, instead of `auto up alignas(1) = (int const *)p;` . This is pointer typecasting from void to int ? – sonus21 Aug 17 '15 at 13:48
  • 1
    @IInspectable, the memory model describes how memory operations behave in the presence of multiple threads, but that's not relevant here. Alignment requirements have always been part of C++. – Jonathan Wakely Aug 17 '15 at 14:03
  • @Barry, [basic.lval] says you can't read from an lvalue if there isn't an object of that type at that location, and [basic.life] says you need suitably aligned storage for an object to begin its lifetime. – Jonathan Wakely Aug 17 '15 at 14:09
  • @JonathanWakely Even with taking the address of an unaligned member of a packed struct? – Barry Aug 17 '15 at 14:17
  • @Barry, packed structs are the devil's work, but are inherently non-standard, so in implementation-defined territory. If the compiler supports packed structs then the members are (as far as that compiler is concerned) suitably aligned. The standard says nothing about such things, but does explicitly say that `alignas` cannot be used to reduce alignment requirements. – Jonathan Wakely Aug 17 '15 at 14:26

3 Answers3

4

To read an unaligned integer:

int i;
void* ptr_to_unaligned;
...
memcpy (&i, ptr_to_unaligned, sizeof(i));

There is no unaligned integer type in C++, so you have to make do with void*.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
3

Trying to convert a pointer to void to a type with alignment requirement invokes undefined behaviour, according to C++11 draft (n4296)

From 5.2.9 Static cast §13 : A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T,” where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1... If the original pointer value represents the address A of a byte in memory and A satisfies the alignment requirement of T, then the resulting pointer value represents the same address as the original pointer value, that is, A. The result of any other such pointer conversion is unspecified (emphasize mine)

I know you are using an explicit cast (or C-style cast), but 5.4 Explicit cast says: The conversions performed by a const_cast (5.2.11), a static_cast (5.2.9), a static_cast followed by a const_cast, a reinterpret_cast (5.2.10), or a reinterpret_cast followed by a const_cast, can be performed using the cast notation of explicit type conversion. The same semantic restrictions and behaviors apply...

So in your case, the explicit cast is the same of static_cast<int const *>(p).

And some architectures, notably ARM architecture are know to trap when you try to access unaligned int pointers as said in that other SO answer

Community
  • 1
  • 1
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • It is not directly an answer and was originally posted as a comment, but I wanted to add references which could not fit in a comment. – Serge Ballesta Aug 17 '15 at 13:32
  • Also [basic.life] says that an object's lifetime starts when suitably sized and aligned storage is obtained (and if relevant, its constructor runs). If you don't have suitably aligned storage no object can be created at that address, and so by [basic.lval] it is undefined behaviour to read a value from that address because there is no object of that dynamic type at that address. – Jonathan Wakely Aug 17 '15 at 14:06
1

To use an integer in an unaligned way, put the word __packed in front of the integer pointer declaration:

__packed int *pi; // pointer to unaligned int

Unaligned pointers in C and C++ code

Russell Hankins
  • 1,196
  • 9
  • 17