0

I have an array type of char which is global. I wanted starting address to be aligned with 32 bit. When I checked the virtual address in map file, it was xxxxxx56H. How can align the starting address to be multiple of 32bit. I need generic solution not compiler dependent solution. I have tried

#pragma pack(32)
char array[223];
#pragma pack

But not working.

P.S : In order to align with 32 bit, last two bit of address should be 0.

user3429606
  • 187
  • 1
  • 1
  • 9
  • 32 bits is 4 bytes? No standard memory allocator will provide data that is not at least 4-byte aligned (it will usually be at least 8-byte aligned) because the memory provided must be usable for any purpose. Or did you mean 32 bytes? For C, see [How to allocate aligned memory only using the standard library?](https://stackoverflow.com/questions/227897/) However, that is primarily about dynamically allocated memory; not global variables. – Jonathan Leffler Jul 18 '17 at 15:07
  • I need the starting address of array to aligned with 32 bits (Multiples of 4 like xxxxxx00 or xxxxxx04 or xxxxxx08 or xxxxxx0c and so on). Not Bytes. Which also means the last two bit of address to be zero. – user3429606 Jul 18 '17 at 15:13
  • @JonathanLeffler: On platforms with less than 32 bits, this is not uncommon. – too honest for this site Jul 18 '17 at 15:26
  • @Olaf: I referred to a standard memory allocator, meaning `malloc()` et al. A global variable of type `char` can be on any type of boundary — on any type of machine. Global arrays of `char` are not necessarily aligned on an even boundary, or more stringently, on any platform, unless appropriately qualified with `_Alignas` (or `alignas` if you've included ``). – Jonathan Leffler Jul 18 '17 at 16:11
  • @ Jonathan Leffler is it possible to have char array starting address aligned with 4 byte using #pragma or __attribute__. – user3429606 Jul 18 '17 at 16:15
  • @JonathanLeffler: That's what I understood, too. It was not uncommon on smaller platforms to have an alignment of 1 byte/octet or 16 bits. Agreed, this is not common, because those are nowadays only embedded systems which typically don't use dynamic memory allocation, but it was quite common some time ago. (Considering the Turbo-C questions here, I have the impression it still is). – too honest for this site Jul 18 '17 at 16:19
  • Do you really mean **bits**?? From the snippet, it looks more like you mean **bytes**. Please clarify **in the question** – too honest for this site Jul 18 '17 at 16:31
  • Yes it is bits. I tried wrong one in code snippet assuming input to pack is bits. – user3429606 Jul 18 '17 at 16:33
  • @user3429606: C has no concept of bit-addressing. Better you **consistently** use bytes (or `char`s). Nevertheless, it starts smelling like an XY-problem. **Why** do you want the alignment? Read my answer for vital information. Please also read [ask] and provide the required information. – too honest for this site Jul 18 '17 at 16:39
  • @user3429606 Why does code need a 32-bit alignment? – chux - Reinstate Monica Jul 18 '17 at 17:16
  • @chux Thats a condition before coping to processor register. address should be copied to register and that should be aligned with 32 bit. – user3429606 Jul 18 '17 at 17:53
  • It sounds like a _better_ question is "How to align an array per the processor's most stringent requirements." be it 4, 16, 1, or `n`. This is a more useful question and addresses your needs as well as others platforms. It is simpler to answer than "Aligning starting address of array to be multiples of 32 bit?" which has an artificial requirement of 4 byte alignment (which might not even be possible on systems that require 8). – chux - Reinstate Monica Jul 18 '17 at 18:17
  • Why don't you just over allocate and align manually using `/4*4`? – Ajay Brahmakshatriya Jul 19 '17 at 06:06
  • @AjayBrahmakshatriya: Because that invokes undefined behaviour **and** implementation defined behaviour. – too honest for this site Jul 21 '17 at 20:03

2 Answers2

3

Packing is something completely unrelated. To align a static variable or struct member (relative to the struct start), use the standard _Alignas specifier.

If you need the maximum alignment (i.e. an alignment suitable for any type) on your platform, use max_align_t, for a specific alignment of bytes, just specify the alignment as constant expression:

_Alignas(32 / CHAR_BIT) char a[10];

(This will cause problems if there is a remainder for the division; Did you really mean 32 bits or 32 bytes? A byte is not guaranteed by the standard to have 8 bits.)

If you intend to cast the array to any other type, you still invoke undefined behaviour by violating the effective type (aka strict aliasing) rule. Use the correct type for the array and use the larger of alignments of the type or whatever you want using e.g. the conditional operator:

Alignas(_Alignof(int) > 8 ? _Alignof(int) : 8) int a[10];
too honest for this site
  • 12,050
  • 4
  • 30
  • 52
  • Is it applicable for C – user3429606 Jul 18 '17 at 15:52
  • @user3429606: yes, it is C11. – Jonathan Leffler Jul 18 '17 at 16:02
  • @user3429606: I intentionally linked to the C standard (the final draft more precisely, but that makes no difference). It is a good reading in general to find out about the language. – too honest for this site Jul 18 '17 at 16:05
  • @user3429606: Please remember to accept/upvote if that answr solved your problem (it does, unless you use a compiler outdated since 6 years). – too honest for this site Jul 18 '17 at 16:11
  • I am getting "parse error near '16' " compilation error. On this line _Alignas (16) char array[223]; – user3429606 Jul 18 '17 at 16:11
  • @user3429606: Does your compiler support C11? Have you set it into C11 mode? If it isn't running in C11 mode, or isn't capable of supporting C11, then you have to look at your compiler's manual to see what, if anything, it provides. If it doesn't provide anything, you may have to go to some lengths to achieve an ad hoc effect equivalent to `_Alignas`. I'm thinking unions, or structures, containing a suitably aligned type as well as the array, and changed references. Or possibly a pointer to the array in a union or structure. It gets fiddly pretty quick, which is why C11 is useful. – Jonathan Leffler Jul 18 '17 at 16:14
  • @user3429606: Please understand we are not a debugging service. I made clear you need a modern compiler; without more information we have to assume you use a standard compliant compiler like gcc or clang. For older compilers, there is no way to use this **portably** which you explicitly asked for. In general, the C standard commitee has a policy to add only features if they cannot be achieved with existing features. – too honest for this site Jul 18 '17 at 16:14
  • @JonathanLeffler: OP explicitly asked about a portable and non-compiler dependent way. I don't see how this can be achieved without this standard feature (which is the reason it was added to the standard). – too honest for this site Jul 18 '17 at 16:17
  • 1
    @chqrlie: That's only for struct member packing, not for alignment of static or automatic variables. It is also not portable which was explicitly asked for. Just don't use rubbish, outdated compilers. – too honest for this site Jul 18 '17 at 16:28
2

A somewhat portable way to define an array of char aligned on 32 bit boundaries is this:

union {
    char array[223];
    unsigned long ul;
} u;

u will be aligned on a 32-bit boundary or possibly a larger power of 2 if type unsigned long requires it, which is very probable on your system. The array is accessed as u.array. No pragmas, no C11 specific syntax, no compiler specific extension.

If type uint32_t is available, you could use it in place of unsigned long.

This solution is not really portable, but a work around for outdated compilers that do not support the _Alignas specifier. Your compiler does not seem up to date with the current (or the previous) C Standard.

The only correct solution is to use the _Alignas specifier. If you give more context such as what system and compiler you use and why you need 32-bit alignment, a better solution could be found for your problem.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • I'm not sure if OP asked about a 32 **bit** or 32 **byte** alignment. And this is not portable. – too honest for this site Jul 18 '17 at 16:30
  • 1
    @Olaf: the OP unambiguously wants 32-bit alignment: *In order to align with 32 bit, last two bit of address should be 0.* What is not portable in my proposal? – chqrlie Jul 18 '17 at 16:33
  • "`#pragma pack(32)`" Would provide a 32 **byte** alignment (in a `struct`). But yes, maybe there is a missunderstanding. It is not portable, because there is no alignment requirement for any type in the language. – too honest for this site Jul 18 '17 at 16:35
  • @Olaf: Yes there is a misunderstanding. There is indeed no alignment requirement, but this is as close as it gets if he wants a compiler independent solution. – chqrlie Jul 18 '17 at 16:37
  • Not really. I provided a completely compiler-independent solution in my answer. After 6 years, every modern compiler supports this. And as you already agreed there is no alignment requirement, how can this solution be "compiler independent" at all? In fact most platforms will not fulfill this. – too honest for this site Jul 18 '17 at 16:41
  • 1
    @Olaf: your solution, which I would condone, is not really portable to pre-C11 compilers. The OP might be using VS2010 which does not even support C99. – chqrlie Jul 18 '17 at 16:43
  • That's why one should not use such ancient compilers. There is no need to use them on larger platforms. Btw. MSVC++ supports them in C++ code. From their policy to support common features in both languages, it is quite likely they also support it in C code, too. Just get a recent version. We cannot support all ancient/outdated versions of C compilers; especially without more information. Anyway, the more I think about the question, the more it smells like an XY problem. – too honest for this site Jul 18 '17 at 16:49
  • This does not work to certainly align data on a 32-bit (4 byte) address as it relies on `ul` requiring at least that alignment multiple. If a `ul` as a `long`, `int32_t`, `float`, etc only required a 1 byte alignment (8-bit embedded processors come to mind) , then `char array[223];` is not more aligned. IAC, the _need_ for this alignment is not stated for this xy post. – chux - Reinstate Monica Jul 18 '17 at 17:15