Discussion:
_Alignof can't have an expression operand
(too old to reply)
Keith Thompson
2017-02-19 03:35:18 UTC
Permalink
Raw Message
The _Alignof operator, added in C11, is similar to the sizeof operator.
One difference is that the operand of sizeof can be either an expression
(specifically a unary-expression) or a parenthesized type-name, but the
operand of _Alignof can only be a parenthesized type-name. I asked
about the reason for this here several years ago; Larry Jones, a
committee member, didn't know the answer.

I just took a look at some of the pre-C11 drafts from
http://www.open-std.org/jtc1/sc22/wg14/www/docs/

n1401.pdf, dated 2009-09-28 didn't have alignof.
n1425.pdf, dated 2009-12-24, added it with the syntax
alignof ( type-name )
with "alignof" being a new keyword. This was unchanged up
to and including n1547.pdf, 2010-12-02.
n1570.pdf, dated 2011-04-11, the most recent public draft, has
_Alignof ( type-name )
with "alignof" defined as a macro in <stdalign.h>.

The earliest reference I've found to alignof in C is
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1397.htm,
"Adding Alignment Support to C", dated 2009-09-25. It has
"alignof" as a keyword.

None of these documents mention the possibility of permitting an
expression operand, or say anything about why it's not permitted.

Apparently "alignof" was borrowed from C++, which has "alignof"
as a keyword and also doesn't permit an expression operand.
I haven't looked through the C++ drafts to figure out how that
decision was made.

(I'm not actually sure that `alignof expr` would be all that useful.
The asymmetry between alignof and sizeof just seemed odd.)
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Keith Thompson
2017-02-19 06:32:01 UTC
Permalink
Raw Message
Keith Thompson <kst-***@mib.org> writes:
[...]
Post by Keith Thompson
Apparently "alignof" was borrowed from C++, which has "alignof"
as a keyword and also doesn't permit an expression operand.
I haven't looked through the C++ drafts to figure out how that
decision was made.
I've found this document:
http://open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1546.pdf
dated 2002-05-02 to 2003-11-17 which appears to be the earlier proposal
for alignof in C++.

Section 4.1.2 discusses a proposed "align_of" operator:

The align_of operator retrieves - during compile time - the
alignment-value associated with a type. It is an unary-expression
and takes the following form:
unary-expression:
align_of(type-id)
Its value is an integral constant-expression of type std::size_t.

but the examples use a different syntax, similar to a template or
C++-style cast operator:

const std::ptrdiff_t intAlign = align_of<int>;

(The use of ptrdiff_t rather than size_t in the example is also odd.)

I suspect that the original concept was that alignof (the choice beween
"align_of" and "alignof" is mentioned as an open question) was
originally intended to use a <> syntax similar to the C++-style cast
operators. Given that, it probably made sense for it to apply only to
type names. When the syntax was later changed to something more similar
to sizeof, that decision may not have been revisited.
Post by Keith Thompson
(I'm not actually sure that `alignof expr` would be all that useful.
The asymmetry between alignof and sizeof just seemed odd.)
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Keith Thompson
2017-02-19 15:40:32 UTC
Permalink
Raw Message
Keith Thompson <kst-***@mib.org> writes:
[...]
Post by Keith Thompson
I suspect that the original concept was that alignof (the choice beween
"align_of" and "alignof" is mentioned as an open question) was
originally intended to use a <> syntax similar to the C++-style cast
operators. Given that, it probably made sense for it to apply only to
type names. When the syntax was later changed to something more similar
to sizeof, that decision may not have been revisited.
[...]

For anyone who's interested, N1546 discusses the choice of template-like
syntax vs. sizeof-like syntax in section 6.7.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Tim Rentsch
2017-02-19 09:41:18 UTC
Permalink
Raw Message
Post by Keith Thompson
The _Alignof operator, added in C11, is similar to the sizeof operator.
One difference is that the operand of sizeof can be either an expression
(specifically a unary-expression) or a parenthesized type-name, but the
operand of _Alignof can only be a parenthesized type-name. I asked
about the reason for this here several years ago; Larry Jones, a
committee member, didn't know the answer.
I just took a look at some of the pre-C11 drafts from
http://www.open-std.org/jtc1/sc22/wg14/www/docs/
n1401.pdf, dated 2009-09-28 didn't have alignof.
n1425.pdf, dated 2009-12-24, added it with the syntax
alignof ( type-name )
with "alignof" being a new keyword. This was unchanged up
to and including n1547.pdf, 2010-12-02.
n1570.pdf, dated 2011-04-11, the most recent public draft, has
_Alignof ( type-name )
with "alignof" defined as a macro in <stdalign.h>.
The earliest reference I've found to alignof in C is
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1397.htm,
"Adding Alignment Support to C", dated 2009-09-25. It has
"alignof" as a keyword.
None of these documents mention the possibility of permitting an
expression operand, or say anything about why it's not permitted.
[...]
If you could somehow magically know the answer, what would
it get you?
Keith Thompson
2017-02-19 15:17:40 UTC
Permalink
Raw Message
[...]
Post by Tim Rentsch
Post by Keith Thompson
None of these documents mention the possibility of permitting an
expression operand, or say anything about why it's not permitted.
[...]
If you could somehow magically know the answer, what would
it get you?
The answer. Why do you ask?
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Tim Rentsch
2017-02-24 23:24:17 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by Tim Rentsch
Post by Keith Thompson
None of these documents mention the possibility of permitting an
expression operand, or say anything about why it's not permitted.
[...]
If you could somehow magically know the answer, what would
it get you?
The answer. Why do you ask?
I was curious to know if there is something else you hope to
get. I think it's unlikely you're going to find an answer to
the question as stated, and was wondering if there might be
some other way you might reach your goal, whatever that might
be.
Keith Thompson
2017-02-24 23:57:19 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by Keith Thompson
[...]
Post by Tim Rentsch
Post by Keith Thompson
None of these documents mention the possibility of permitting an
expression operand, or say anything about why it's not permitted.
[...]
If you could somehow magically know the answer, what would
it get you?
The answer. Why do you ask?
I was curious to know if there is something else you hope to
get. I think it's unlikely you're going to find an answer to
the question as stated, and was wondering if there might be
some other way you might reach your goal, whatever that might
be.
My motivation was nothing more than curiosity. I found it odd that
sizeof permits either a unary-expression or a parenthesized type-name
as an operand, but the otherwise very similar _Alignof permits only
a parenthesized type-name. (The person who edited N1570 6.3.2.1p2
apparently assumed that _Alignof could take a unary-expression as
its operand; that error was corrected in the published C11 standard.)

I was able to get a plausible, though not terribly satisfying,
explanation (the original concept used C++ template syntax).

But beyond that, someone else in this thread presented a scenario
where _Alignof expr could be useful. Since the reasons I found do
not imply that there's any strong reason *not* to permit _Alignof
expr, it might be worth considering adding it in the next standard.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
s***@casperkitty.com
2017-02-21 23:51:50 UTC
Permalink
Raw Message
Post by Tim Rentsch
If you could somehow magically know the answer, what would
it get you?
If a possibility was considered and rejected for some particular reason,
someone faced with a similar decision who knows why a course was rejected
could save time exploring a possibility that would ultimately turn out to
be unacceptable.

I suspect the authors of the Standard couldn't think of any case in which
_Alignof(expr) would offer any advantage over _Alignof(type), and that any
cost-benefit analysis was seen as zero-benefit vs non-zero cost. I'm not
sure how they would have weight cost vs. benefit if they'd considered the
possibility that an object which is contained within a structure may be
known to satisfy an alignment which is coarser than what the object's type
would require. For example, given:

struct { uint64_t x; uint16_t y[4]; } *fooptr;

if fooptr->x would have an 64-bit alignment requirement, then fooptr->y
could also be guaranteed to be 64-bit aligned even though most things of
type uint16_t would not. If _Alignof could take an expression rather than
just a type, then code which was going to act upon fooptr->y could know at
compile time that it was aligned to the larger size.
Tim Rentsch
2017-02-24 23:27:15 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Tim Rentsch
If you could somehow magically know the answer, what would
it get you?
[...]
I suspect the authors of the Standard couldn't think of any case in
which _Alignof(expr) would offer any advantage over _Alignof(type),
and that any cost-benefit analysis was seen as zero-benefit vs
non-zero cost. [...]
Is this one of your usual suspicions that is purely a fig newton
of your imagination, or do you have some evidence to offer that
supports it?
William Ahern
2017-02-23 00:16:59 UTC
Permalink
Raw Message
Post by Keith Thompson
The _Alignof operator, added in C11, is similar to the sizeof operator.
One difference is that the operand of sizeof can be either an expression
(specifically a unary-expression) or a parenthesized type-name, but the
operand of _Alignof can only be a parenthesized type-name.
<snip>
Post by Keith Thompson
(I'm not actually sure that `alignof expr` would be all that useful.
The asymmetry between alignof and sizeof just seemed odd.)
A quick grep of my local source code dumping grounds found this usage in
glibc/string/strcoll_l.c [1]

assert (((uintptr_t) table) % __alignof__ (table[0]) == 0);
assert (((uintptr_t) weights) % __alignof__ (weights[0]) == 0);
assert (((uintptr_t) extra) % __alignof__ (extra[0]) == 0);
assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0);

Relying on a GCC extension[2], the code checks that the pointers are
properly aligned for their type, without having to explicitly specify the
type name. The preference for using an expression would be the same as for
sizeof; namely, that specifying the relevant expression is more resiliant to
typos and, especially, to subsequent code refactoring.

While that was the only instance I found, surveying a few other usages of
alignof I found that specifying an expression would have been, I think,
preferable in many cases. Generalizing, just about anywhere a pointer to
char data is coerced to another pointer type for manipulation, and where
alignof would be called upon, it would be preferable to specify an
expression. If you have the object you're about to manipulate at hand,
better to provide it to the compiler rather than indirectly specifying a
characteristic of that object. Any indirection that is invisible to the
compiler should be avoided as much as is practicable. I think GCC's
extension is practical.

[1] https://sourceware.org/git/?p=glibc.git;a=blob;f=string/strcoll_l.c;h=7e8fbf3895cc5b92f3a5990315e0a041b9ba3cc2;hb=HEAD#l288
[2] https://gcc.gnu.org/onlinedocs/gcc/Alignment.html
s***@casperkitty.com
2017-02-23 00:58:10 UTC
Permalink
Raw Message
Post by William Ahern
While that was the only instance I found, surveying a few other usages of
alignof I found that specifying an expression would have been, I think,
preferable in many cases. Generalizing, just about anywhere a pointer to
char data is coerced to another pointer type for manipulation, and where
alignof would be called upon, it would be preferable to specify an
expression. If you have the object you're about to manipulate at hand,
better to provide it to the compiler rather than indirectly specifying a
characteristic of that object. Any indirection that is invisible to the
compiler should be avoided as much as is practicable. I think GCC's
extension is practical.
The authors of the Standard may have thought that one could use something
like "alignof(typeof(foo))" in cases where one wanted the alignment, even
though the latter wouldn't indicate whether "foo" had some known alignment
which was stronger than required for its type.

BTW, even though gcc adds an extension which would make it useful to
recognize that sizeof x might differ from the size of its type (i.e. the
ability to auto-size a flexible array member to fit an initialization
list), applying sizeof to a such an object omits the size of the flexible
part, severely degrading the usefulness of that feature.
Keith Thompson
2017-02-23 01:27:05 UTC
Permalink
Raw Message
***@casperkitty.com writes:
[...]
Post by s***@casperkitty.com
The authors of the Standard may have thought that one could use something
like "alignof(typeof(foo))" in cases where one wanted the alignment, even
though the latter wouldn't indicate whether "foo" had some known alignment
which was stronger than required for its type.
The authors of the standard were and are perfectly well aware that C has
no "typeof" feature.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Wojtek Lerch
2017-02-23 03:05:05 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
The authors of the Standard may have thought that one could use something
like "alignof(typeof(foo))" in cases where one wanted the alignment, even
I would definitely think that "typeof" would be a more useful addition
to C than "alignof(expr)" would be.
Post by s***@casperkitty.com
though the latter wouldn't indicate whether "foo" had some known alignment
which was stronger than required for its type.
C does not even define the alignment of an expression, does it? How
would you define it, if not as the alignment of its type? Would you
restrict it to lvalues only?

Imagine that "foo" is a static object that the compiler knows to be
located at a multiple of 256 bytes; the linker knows it to be located at
a multiple of 4K; and the loader sometimes locates it at a multiple of
16K. What would your definition of alignof(foo) yield?
Keith Thompson
2017-02-23 03:51:06 UTC
Permalink
Raw Message
Post by Wojtek Lerch
Post by s***@casperkitty.com
The authors of the Standard may have thought that one could use something
like "alignof(typeof(foo))" in cases where one wanted the alignment, even
I would definitely think that "typeof" would be a more useful addition
to C than "alignof(expr)" would be.
It doesn't have to be just one or the other.
Post by Wojtek Lerch
Post by s***@casperkitty.com
though the latter wouldn't indicate whether "foo" had some known alignment
which was stronger than required for its type.
C does not even define the alignment of an expression, does it? How
would you define it, if not as the alignment of its type? Would you
restrict it to lvalues only?
Yes, it would be the alignment of the expression's type, just as for
sizeof.
Post by Wojtek Lerch
Imagine that "foo" is a static object that the compiler knows to be
located at a multiple of 256 bytes; the linker knows it to be located at
a multiple of 4K; and the loader sometimes locates it at a multiple of
16K. What would your definition of alignof(foo) yield?
The required alignment of its type. It wouldn't give you the alignment
that some particular object happens to have. (That might or might be a
useful feature itself.)
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Wojtek Lerch
2017-02-23 04:42:54 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Wojtek Lerch
Post by s***@casperkitty.com
The authors of the Standard may have thought that one could use something
like "alignof(typeof(foo))" in cases where one wanted the alignment, even
I would definitely think that "typeof" would be a more useful addition
to C than "alignof(expr)" would be.
It doesn't have to be just one or the other.
No, but if we had the first one, the other would be redundant and
unnecessary -- unless alignof(expr) were defined to be something other
than the equivalent of alignof(typeof(expr)).
Post by Keith Thompson
Post by Wojtek Lerch
Post by s***@casperkitty.com
though the latter wouldn't indicate whether "foo" had some known alignment
which was stronger than required for its type.
C does not even define the alignment of an expression, does it? How
would you define it, if not as the alignment of its type? Would you
restrict it to lvalues only?
Yes, it would be the alignment of the expression's type, just as for
sizeof.
Well no, apparently Supercat would want "alignof(foo)" to indicate when
"foo" had "some known alignment which was stronger than required for its
type".
Post by Keith Thompson
Post by Wojtek Lerch
Imagine that "foo" is a static object that the compiler knows to be
located at a multiple of 256 bytes; the linker knows it to be located at
a multiple of 4K; and the loader sometimes locates it at a multiple of
16K. What would your definition of alignof(foo) yield?
The required alignment of its type. It wouldn't give you the alignment
that some particular object happens to have. (That might or might be a
useful feature itself.)
But my point is that objects don't have an alignment. An object has an
address. The address is guaranteed to satisfy the alignment
requirements of the object's type, and may also happen to satisfy one or
more stricter alignments at the same time. C does not define such a
thing as "the alignment" of an object -- adding alignof(expr) to the
language would have to involve deciding what its value would be, and it
seems that you and Supercat have different opinions on that.
s***@casperkitty.com
2017-02-23 16:16:32 UTC
Permalink
Raw Message
Post by Wojtek Lerch
But my point is that objects don't have an alignment. An object has an
address. The address is guaranteed to satisfy the alignment
requirements of the object's type, and may also happen to satisfy one or
more stricter alignments at the same time. C does not define such a
thing as "the alignment" of an object -- adding alignof(expr) to the
language would have to involve deciding what its value would be, and it
seems that you and Supercat have different opinions on that.
I'm not calling upon _Alignof to affirmatively indicate the coarsest
alignment than an object's address happens to satisfy, but rather the
coarsest alignment which the compiler can conveniently statically
guarantee that the object's alignment satisfies. If a compiler includes
something equivalent to __builtin_constant_p(), that could be combined
with an _Alignof to to allow calls to e.g.

// Complement the values of
invert_bytes(void *p, uint32_t n);

to be replaced with calls to

invert_words(void *p, uint32_t n);

in cases where "n" was a constant multiple of four and address p was known
to the compiler to be aligned. When those conditions don't apply, it would
make more sense to have the run-time optimization check performed within
the invert_bytes routine than in the caller, but the only way the code could
benefit from compiler knowledge would be to have the check done caller-side.

I don't know whether a "typeof" operator was under consideration when the
_Alignof was added, but the lack of an expression form would have been
a much more conspicuous omission if no form of "typeof" was expected to
be available.
Wojtek Lerch
2017-02-24 02:46:43 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
I'm not calling upon _Alignof to affirmatively indicate the coarsest
alignment than an object's address happens to satisfy, but rather the
coarsest alignment which the compiler can conveniently statically
guarantee that the object's alignment satisfies.
But why restrict yourself to what the compiler can conveniently
statically guarantee, when you can cheaply compute it for sure at
runtime? From your examples it seems that you don't really need the the
*coarsest* alignment, but merely to find out whether a pointer satisfies
the requirements of a specific type. On most typical implementations
that could be done with a simple macro:

#define satisfies_alignment( pointer, type ) \
( (uintptr_t)(pointer) % _Alignof(type) == 0 )
s***@casperkitty.com
2017-02-24 22:35:53 UTC
Permalink
Raw Message
Post by Wojtek Lerch
Post by s***@casperkitty.com
I'm not calling upon _Alignof to affirmatively indicate the coarsest
alignment than an object's address happens to satisfy, but rather the
coarsest alignment which the compiler can conveniently statically
guarantee that the object's alignment satisfies.
But why restrict yourself to what the compiler can conveniently
statically guarantee, when you can cheaply compute it for sure at
runtime? From your examples it seems that you don't really need the the
*coarsest* alignment, but merely to find out whether a pointer satisfies
the requirements of a specific type. On most typical implementations
#define satisfies_alignment( pointer, type ) \
( (uintptr_t)(pointer) % _Alignof(type) == 0 )
There are many situations where it makes sense to statically evaluate
conditions outside a function when possible, and run-time evaluate them
inside a function when static evaluation is not possible. I'm not sure
how you think any run-time test would be faster than a compile-time test
that takes zero instructions.
Wojtek Lerch
2017-02-25 05:17:15 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Wojtek Lerch
Post by s***@casperkitty.com
I'm not calling upon _Alignof to affirmatively indicate the coarsest
alignment than an object's address happens to satisfy, but rather the
coarsest alignment which the compiler can conveniently statically
guarantee that the object's alignment satisfies.
But why restrict yourself to what the compiler can conveniently
statically guarantee, when you can cheaply compute it for sure at
runtime? From your examples it seems that you don't really need the the
*coarsest* alignment, but merely to find out whether a pointer satisfies
the requirements of a specific type. On most typical implementations
#define satisfies_alignment( pointer, type ) \
( (uintptr_t)(pointer) % _Alignof(type) == 0 )
There are many situations where it makes sense to statically evaluate
conditions outside a function when possible, and run-time evaluate them
inside a function when static evaluation is not possible. I'm not sure
how you think any run-time test would be faster than a compile-time test
that takes zero instructions.
I didn't say it would be faster, did I? I said it would be cheap. But
in those cases where the compiler can statically detect that the pointer
satisfies the check, the optimizer can eliminate the runtime check.
Jakob Bohm
2017-02-27 21:12:58 UTC
Permalink
Raw Message
Post by Wojtek Lerch
Post by s***@casperkitty.com
Post by Wojtek Lerch
Post by s***@casperkitty.com
I'm not calling upon _Alignof to affirmatively indicate the coarsest
alignment than an object's address happens to satisfy, but rather the
coarsest alignment which the compiler can conveniently statically
guarantee that the object's alignment satisfies.
But why restrict yourself to what the compiler can conveniently
statically guarantee, when you can cheaply compute it for sure at
runtime? From your examples it seems that you don't really need the the
*coarsest* alignment, but merely to find out whether a pointer satisfies
the requirements of a specific type. On most typical implementations
#define satisfies_alignment( pointer, type ) \
( (uintptr_t)(pointer) % _Alignof(type) == 0 )
There are many situations where it makes sense to statically evaluate
conditions outside a function when possible, and run-time evaluate them
inside a function when static evaluation is not possible. I'm not sure
how you think any run-time test would be faster than a compile-time test
that takes zero instructions.
I didn't say it would be faster, did I? I said it would be cheap. But
in those cases where the compiler can statically detect that the pointer
satisfies the check, the optimizer can eliminate the runtime check.
Unfortunately, compilers tend to emit a warning diagnostic (which may
stop compilation with "warnings as error" options in effect) whenever
they detect that a runtime boolean condition is always true or always
false.

While such warnings are obviously intended to catch tests that were
accidentally wrong (such as some off-by one bugs), they also discourage
the writing of code that hopes to be optimized out, forcing programmers
to write convoluted compile time tests to determine if a runtime test
can be omitted in some compiles of a portable C program.


Enjoy

Jakob
--
Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com
Transformervej 29, 2860 Søborg, Denmark. Direct +45 31 13 16 10
This public discussion message is non-binding and may contain errors.
WiseMo - Remote Service Management for PCs, Phones and Embedded
Wojtek Lerch
2017-02-28 03:38:12 UTC
Permalink
Raw Message
Post by Jakob Bohm
Post by Wojtek Lerch
Post by s***@casperkitty.com
Post by Wojtek Lerch
Post by s***@casperkitty.com
I'm not calling upon _Alignof to affirmatively indicate the coarsest
alignment than an object's address happens to satisfy, but rather the
coarsest alignment which the compiler can conveniently statically
guarantee that the object's alignment satisfies.
But why restrict yourself to what the compiler can conveniently
statically guarantee, when you can cheaply compute it for sure at
runtime? From your examples it seems that you don't really need the the
*coarsest* alignment, but merely to find out whether a pointer satisfies
the requirements of a specific type. On most typical implementations
#define satisfies_alignment( pointer, type ) \
( (uintptr_t)(pointer) % _Alignof(type) == 0 )
There are many situations where it makes sense to statically evaluate
conditions outside a function when possible, and run-time evaluate them
inside a function when static evaluation is not possible. I'm not sure
how you think any run-time test would be faster than a compile-time test
that takes zero instructions.
I didn't say it would be faster, did I? I said it would be cheap. But
in those cases where the compiler can statically detect that the pointer
satisfies the check, the optimizer can eliminate the runtime check.
Unfortunately, compilers tend to emit a warning diagnostic (which may
stop compilation with "warnings as error" options in effect) whenever
they detect that a runtime boolean condition is always true or always
false.
I don't think it's as simple as that; in my experience it depends on
*why* the condition is always true or always false. Anyway, do you have
any reason to suspect that my macro would be more likely to provoke such
a warning than Supercat's proposal with _Alignof(expr) would?
Post by Jakob Bohm
While such warnings are obviously intended to catch tests that were
accidentally wrong (such as some off-by one bugs), they also discourage
the writing of code that hopes to be optimized out, forcing programmers
to write convoluted compile time tests to determine if a runtime test
can be omitted in some compiles of a portable C program.
Personally, I tend to prefer compile-time tests for a different reason:
because they let me make sure that no dead code stays in, regardless of
how badly I overestimate the optimizer (or underestimate the difficulty
of its job). But I've written code both ways, and don't recall ever
seeing warnings that would discourage me to do so. There have been many
cases in my life where I complained and cursed about warnings, but
usually it's about other kinds of warnings than this.
Tim Rentsch
2017-02-24 23:47:46 UTC
Permalink
Raw Message
Post by Wojtek Lerch
Post by Keith Thompson
Post by Wojtek Lerch
Post by s***@casperkitty.com
The authors of the Standard may have thought that one could use something
like "alignof(typeof(foo))" in cases where one wanted the alignment, even
I would definitely think that "typeof" would be a more useful addition
to C than "alignof(expr)" would be.
It doesn't have to be just one or the other.
No, but if we had the first one, the other would be redundant and
unnecessary -- unless alignof(expr) were defined to be something other
than the equivalent of alignof(typeof(expr)).
Post by Keith Thompson
Post by Wojtek Lerch
Post by s***@casperkitty.com
though the latter wouldn't indicate whether "foo" had some known alignment
which was stronger than required for its type.
C does not even define the alignment of an expression, does it? How
would you define it, if not as the alignment of its type? Would you
restrict it to lvalues only?
Yes, it would be the alignment of the expression's type, just as for
sizeof.
Well no, apparently Supercat would want "alignof(foo)" to indicate
when "foo" had "some known alignment which was stronger than required
for its type".
Post by Keith Thompson
Post by Wojtek Lerch
Imagine that "foo" is a static object that the compiler knows to be
located at a multiple of 256 bytes; the linker knows it to be located at
a multiple of 4K; and the loader sometimes locates it at a multiple of
16K. What would your definition of alignof(foo) yield?
The required alignment of its type. It wouldn't give you the alignment
that some particular object happens to have. (That might or might be a
useful feature itself.)
But my point is that objects don't have an alignment. An object has
an address. The address is guaranteed to satisfy the alignment
requirements of the object's type, and may also happen to satisfy one
or more stricter alignments at the same time. C does not define such
a thing as "the alignment" of an object -- adding alignof(expr) to the
language would have to involve deciding what its value would be, and
it seems that you and Supercat have different opinions on that.
Are you assuming that an _Alignas specification has an effect on
the type of a declared identifier? I believe it does not.
Syntactically _Alignas looks like it participates in determining
the type for a declaration, but semantically it operates more
like a storage class: the alignment specification attaches
directly to the identifer(s) being declared, not their types.
For example, in this declaration

_Alignas(8) int foo, *bas;

it is the objects referred to by 'foo' and 'bas' that have their
alignment specified. AFAIK there is no way to make a type that
has an _Alignas(8) condition (or any other alignment value).

I also have a related question. Does N1570 have a bug in its
syntax for struct definitions? The text pretty clearly implies
that, eg, the following

struct foobas {
_Alignas(8) int x;
};

is supposed to be allowed (and gcc -std=c11 -pedantic accepts it
without complaint), but I don't see how the syntax allows it.
Am I missing something obvious? Or was this perhaps corrected
in the official standard?
Keith Thompson
2017-02-25 00:50:29 UTC
Permalink
Raw Message
Tim Rentsch <***@alumni.caltech.edu> writes:
[...]
Post by Tim Rentsch
I also have a related question. Does N1570 have a bug in its
syntax for struct definitions? The text pretty clearly implies
that, eg, the following
struct foobas {
_Alignas(8) int x;
};
is supposed to be allowed (and gcc -std=c11 -pedantic accepts it
without complaint), but I don't see how the syntax allows it.
Am I missing something obvious? Or was this perhaps corrected
in the official standard?
I think you're right.

N1570 and C11 6.7.5p2 both say, in a Constraints section:

An alignment attribute shall not be specified in a declaration
of a typedef, or a bit-field, or a function, or a parameter,
or an object declared with the register storage-class specifier.

The including of bit-fields in that list certainly implies
(though not rigorously) that an alignment attribute is allowed in
a non-bit-field struct (or union) member declaration. (Aside: I
wonder why the text uses the phrase "alignment attribute" rather
than "alignment specifier".) But the grammar does not allow an
alignment-specifier in a struct-declaration.

This is not corrected in C11.

(I wouldn't mind if somebody else double-checked this.)
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Tim Rentsch
2017-02-26 18:51:48 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by Tim Rentsch
I also have a related question. Does N1570 have a bug in its
syntax for struct definitions? The text pretty clearly implies
that, eg, the following
struct foobas {
_Alignas(8) int x;
};
is supposed to be allowed (and gcc -std=c11 -pedantic accepts it
without complaint), but I don't see how the syntax allows it.
Am I missing something obvious? Or was this perhaps corrected
in the official standard?
I think you're right.
An alignment attribute shall not be specified in a declaration
of a typedef, or a bit-field, or a function, or a parameter,
or an object declared with the register storage-class specifier.
The including of bit-fields in that list certainly implies
(though not rigorously) that an alignment attribute is allowed in
a non-bit-field struct (or union) member declaration. (Aside: I
wonder why the text uses the phrase "alignment attribute" rather
than "alignment specifier".) But the grammar does not allow an
alignment-specifier in a struct-declaration.
This is not corrected in C11.
Thank you for checking on that. There is also 6.7.5 p2 (emphasis
added):

The combined effect of all alignment attributes in a
declaration shall not specify an alignment that is less
strict than the alignment that would otherwise be required
for the type of the object _or member_ being declared.

which I would say pretty much settles the issue about whether
members are meant to be included.

After seeing this I noticed something else. What about the "one
special guarantee" rule? 6.5.2.3 p6 in N1570 says (in part):

Two structures share a common initial sequence if
corresponding members have compatible types (and, for
bit-fields, the same widths) for a sequence of one or
more initial members.

But surely that is not meant to apply when one member (after the
first) has a more strict alignment value than its corresponding
member in another struct type. Another bug? Shouldn't this too
be corrected to say, eg, "compatible types and equal alignments",
or something else along similar lines?

I should go and check the DR's, but this morning I'm too lazy to
do that.
s***@casperkitty.com
2017-02-26 23:37:41 UTC
Permalink
Raw Message
Post by Tim Rentsch
After seeing this I noticed something else. What about the "one
Two structures share a common initial sequence if
corresponding members have compatible types (and, for
bit-fields, the same widths) for a sequence of one or
more initial members.
But surely that is not meant to apply when one member (after the
first) has a more strict alignment value than its corresponding
member in another struct type. Another bug? Shouldn't this too
be corrected to say, eg, "compatible types and equal alignments",
or something else along similar lines?
The C89 Standard relied heavily upon readers being able to use common sense,
recognizing that an implementation's intended target and purpose may affect
what behaviors should be considered sensible. Given that the optimization
needs of compilers in certain fields have changed, many of the constraints
[in the English-language sense of the word] that the Standard imposes upon
memory layout often cost more than they did in 1989. Further, aggressive
optimizations often undermine the useful purposes that such constraints once
served. Performance and compatibility would be better served by having
compilers provide a mode which is not only conforming but offers behavioral
guarantees beyond what the Standard requires, so as to make the layout
restrictions useful, and then a more aggressive optimizing mode which would
not claim to be conforming, but would not be bound by layout restrictions
which for some programs would be simultaneously costly and useless.

While it would be reasonable to note that the CIS rule does not apply in
cases where structure members are forced to have different offsets, I don't
think the failure to do so should cause problems if compiler writers and
programmers used common sense. A more interesting question is whether it
is worth keeping in the form that compilers like gcc now treat it.
Ike Naar
2017-02-27 08:15:31 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
While it would be reasonable to note that the CIS rule does not apply in
cases where structure members are forced to have different offsets, I don't
think the failure to do so should cause problems if compiler writers and
programmers used common sense.
What does the 'so' refer to? The structure of the sentence suggests
that it refers to 'note'. In that case, you don't think that a
failure to [note something obvious] should cause problems. That
seems strange. What are you trying to say? Can you re-phrase the
sentence without unnecessary negations?
Post by s***@casperkitty.com
A more interesting question is whether it
is worth keeping in the form that compilers like gcc now treat it.
Are words missing from this sentence?
s***@casperkitty.com
2017-02-27 18:00:58 UTC
Permalink
Raw Message
Post by Ike Naar
Post by s***@casperkitty.com
While it would be reasonable to note that the CIS rule does not apply in
cases where structure members are forced to have different offsets, I don't
think the failure to do so should cause problems if compiler writers and
programmers used common sense.
What does the 'so' refer to? The structure of the sentence suggests
that it refers to 'note'. In that case, you don't think that a
failure to [note something obvious] should cause problems. That
seems strange. What are you trying to say? Can you re-phrase the
sentence without unnecessary negations?
By "note" I meant "explicitly specify". Even though the Standard does not
explicitly specify that the CIS rule does not apply in cases where structs
are explicitly forced to have incompatible layouts, I don't think that any
reasonable programmer would expect the CIS rule to apply in such case.
The significance of such omission is thus trivial compared with the failure
to specify whether the existence of visible and complete definition of a
union type containing two structure with a common initial sequence is meant
to:

1. Imply that compilers should treat a read of a members of the CIS
using a pointer of one structure type as possibly accessing the
corresponding member of another.

2. Imply that the CIS is only relevant to lvalue accesses performed
directly through the union type in question.

3. Behave according to #1 or #2, according to the implementer's judgment
of how best to fulfill the compiler's intended purpose.

C99 conspicuously omits from its examples any which would make clear that
#1 or #2 was intended. I really doubt such an omission was accidental.
A committee member who thought all compilers should uphold #1 should have
regarded as useful an example which made that clear. One who thought that
compilers should not be expected to uphold such a guarantee should have
favored an example which showed that. Unless the authors of the Standard
were being extremely careless, the most likely reason neither example exists
is that there was no consensus, but people favoring each view thought that
in the absence of an example compiler writers would interpret the Standard
in the way they preferred in cases where it mattered [essentially, view #3].
Post by Ike Naar
Post by s***@casperkitty.com
A more interesting question is whether it
is worth keeping in the form that compilers like gcc now treat it.
Are words missing from this sentence?
While the CIS rule is specified in terms of unions, much of its usefulness
from the way it used to allow pointers to different structure types to be
treated interchangeably when used to inspect common members. The way that
gcc interprets the rule, however, makes it pretty much useless. In cases
where code doesn't need to exploit the rule, and where the rule would
prevent what would otherwise be useful optimizations, it would make sense
to let the compiler to abandon the rule altogether.
Wojtek Lerch
2017-02-25 05:19:10 UTC
Permalink
Raw Message
...
Post by Tim Rentsch
Post by Wojtek Lerch
But my point is that objects don't have an alignment. An object has
an address. The address is guaranteed to satisfy the alignment
requirements of the object's type, and may also happen to satisfy one
or more stricter alignments at the same time. C does not define such
a thing as "the alignment" of an object -- adding alignof(expr) to the
language would have to involve deciding what its value would be, and
it seems that you and Supercat have different opinions on that.
Are you assuming that an _Alignas specification has an effect on
the type of a declared identifier? I believe it does not.
No, I had simply forgotten about _Alignas.
Post by Tim Rentsch
Syntactically _Alignas looks like it participates in determining
the type for a declaration, but semantically it operates more
like a storage class: the alignment specification attaches
directly to the identifer(s) being declared, not their types.
Right. So if _Alignof(expr) were to be affected by _Alignas at all, it
would only apply when expr is a declared identifier.

Or maybe the rule for _Alignof(lvalue) could allow the compiler to try
to detect when all the objects that the lvalue can possibly designate
were declared with _Alignas (or came from malloc()) and therefore have
stricter alignment than the type would imply, and the value of
_Alignof() could be allowed to reflect that.
Post by Tim Rentsch
For example, in this declaration
_Alignas(8) int foo, *bas;
it is the objects referred to by 'foo' and 'bas' that have their
alignment specified. AFAIK there is no way to make a type that
has an _Alignas(8) condition (or any other alignment value).
Right. I think it could sometimes be useful if _Alignas() applied to
types the way qualifiers do, especially on machines where the alignment
of some basic types is smaller than their size. On the other hand, a
type whose alignment is greater than its size would have funny
side-effects on arrays and pointer arithmetic -- I guess they would have
to be forbidden for such a type.
Jakob Bohm
2017-02-27 21:26:23 UTC
Permalink
Raw Message
Post by Wojtek Lerch
...
Post by Tim Rentsch
Post by Wojtek Lerch
But my point is that objects don't have an alignment. An object has
an address. The address is guaranteed to satisfy the alignment
requirements of the object's type, and may also happen to satisfy one
or more stricter alignments at the same time. C does not define such
a thing as "the alignment" of an object -- adding alignof(expr) to the
language would have to involve deciding what its value would be, and
it seems that you and Supercat have different opinions on that.
Are you assuming that an _Alignas specification has an effect on
the type of a declared identifier? I believe it does not.
No, I had simply forgotten about _Alignas.
Post by Tim Rentsch
Syntactically _Alignas looks like it participates in determining
the type for a declaration, but semantically it operates more
like a storage class: the alignment specification attaches
directly to the identifer(s) being declared, not their types.
Right. So if _Alignof(expr) were to be affected by _Alignas at all, it
would only apply when expr is a declared identifier.
Or maybe the rule for _Alignof(lvalue) could allow the compiler to try
to detect when all the objects that the lvalue can possibly designate
were declared with _Alignas (or came from malloc()) and therefore have
stricter alignment than the type would imply, and the value of
_Alignof() could be allowed to reflect that.
Post by Tim Rentsch
For example, in this declaration
_Alignas(8) int foo, *bas;
it is the objects referred to by 'foo' and 'bas' that have their
alignment specified. AFAIK there is no way to make a type that
has an _Alignas(8) condition (or any other alignment value).
Right. I think it could sometimes be useful if _Alignas() applied to
types the way qualifiers do, especially on machines where the alignment
of some basic types is smaller than their size. On the other hand, a
type whose alignment is greater than its size would have funny
side-effects on arrays and pointer arithmetic -- I guess they would have
to be forbidden for such a type.
Actually, they would have *useful* effects on arrays and pointer
arithmetic.

Especially in the common case where the requested alignment is needed
to take advantage of some processor capability not used or needed by
the compilation of ordinary code for the same target. For example, it
may be used to ensure that a structure is always aligned to the size of
a processor cache line, thus ensuring it gets read in a single external
RAM cycle.

Another use is to place such an over-aligned type at the beginning or
other tactical location in a structure declaration, thus causing the
entire structure to be nicely aligned consistently with some other
structures doing the same.

At a minimum, it should be permitted for implementations to treat
_AlignAs() as a type qualifier without violating the standard.



Enjoy

Jakob
--
Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com
Transformervej 29, 2860 Søborg, Denmark. Direct +45 31 13 16 10
This public discussion message is non-binding and may contain errors.
WiseMo - Remote Service Management for PCs, Phones and Embedded
Wojtek Lerch
2017-02-28 03:41:27 UTC
Permalink
Raw Message
...
Post by Jakob Bohm
Post by Wojtek Lerch
I think it could sometimes be useful if _Alignas() applied to
types the way qualifiers do, especially on machines where the alignment
of some basic types is smaller than their size. On the other hand, a
type whose alignment is greater than its size would have funny
side-effects on arrays and pointer arithmetic -- I guess they would have
to be forbidden for such a type.
Actually, they would have *useful* effects on arrays and pointer
arithmetic.
Especially in the common case where the requested alignment is needed
to take advantage of some processor capability not used or needed by
the compilation of ordinary code for the same target. For example, it
may be used to ensure that a structure is always aligned to the size of
a processor cache line, thus ensuring it gets read in a single external
RAM cycle.
But I was talking about arrays of an over-aligned type, not structures
containing such a type. Apologies if that wasn't clear enough.

Consider the declaration

_Alignas(sizeof(int64_t)) int32_t arr[ 10 ];

If the _Alignas() were treated as a type qualifier, this would declare
an array whose each element has the type "_Align(sizeof(int64_t))
int32_t". But it's impossible for all the elements to have the
specified alignment, unless there's padding between them; and in C
arrays never have padding between elements.

The way C11 treats _Align(), the above is not illogical: since the
_Align() applies to the whole array rather than to each element, the
declaration creates an array whose every other element is aligned to a
multiple of an int64.
Post by Jakob Bohm
Another use is to place such an over-aligned type at the beginning or
other tactical location in a structure declaration, thus causing the
entire structure to be nicely aligned consistently with some other
structures doing the same.
At a minimum, it should be permitted for implementations to treat
_AlignAs() as a type qualifier without violating the standard.
I'm not sure if I disagree or just misunderstand.

If I write

_Alignas(8) int32_t *ptr;

that tells a C11 compiler that I have special requirements on where my
pointer can sit in memory. But you seem to be saying that compilers
should be allowed to interpret it, instead, as a promise that ptr will
only ever point to special places. I can't imagine a situation where I
wouldn't care which of those two interpretations the compiler chooses.
Jakob Bohm
2017-02-28 08:22:43 UTC
Permalink
Raw Message
Post by Wojtek Lerch
...
Post by Jakob Bohm
Post by Wojtek Lerch
I think it could sometimes be useful if _Alignas() applied to
types the way qualifiers do, especially on machines where the alignment
of some basic types is smaller than their size. On the other hand, a
type whose alignment is greater than its size would have funny
side-effects on arrays and pointer arithmetic -- I guess they would have
to be forbidden for such a type.
Actually, they would have *useful* effects on arrays and pointer
arithmetic.
Especially in the common case where the requested alignment is needed
to take advantage of some processor capability not used or needed by
the compilation of ordinary code for the same target. For example, it
may be used to ensure that a structure is always aligned to the size of
a processor cache line, thus ensuring it gets read in a single external
RAM cycle.
But I was talking about arrays of an over-aligned type, not structures
containing such a type. Apologies if that wasn't clear enough.
Consider the declaration
_Alignas(sizeof(int64_t)) int32_t arr[ 10 ];
If the _Alignas() were treated as a type qualifier, this would declare
an array whose each element has the type "_Align(sizeof(int64_t))
int32_t". But it's impossible for all the elements to have the
specified alignment, unless there's padding between them; and in C
arrays never have padding between elements.
The way C11 treats _Align(), the above is not illogical: since the
_Align() applies to the whole array rather than to each element, the
declaration creates an array whose every other element is aligned to a
multiple of an int64.
Okay, for backward compatibility with the C11 definition, it might be
necessary to specify that the _Alignas() notation has a different
"operator priority" than e.g. "volatile", such that the above would
continue to have the same actual semantics.

Having padding between elements can be a good thing, consider this
example

// Assume sizeof(long double) == 10 or 12, as is common on x86

(_Alignas(8) long double) fasttable[10];

// This (or similar) would pad the array such that none of the
// elements would require extra memory bus cycles to access.
Post by Wojtek Lerch
Post by Jakob Bohm
Another use is to place such an over-aligned type at the beginning or
other tactical location in a structure declaration, thus causing the
entire structure to be nicely aligned consistently with some other
structures doing the same.
At a minimum, it should be permitted for implementations to treat
_AlignAs() as a type qualifier without violating the standard.
I'm not sure if I disagree or just misunderstand.
If I write
_Alignas(8) int32_t *ptr;
that tells a C11 compiler that I have special requirements on where my
pointer can sit in memory. But you seem to be saying that compilers
should be allowed to interpret it, instead, as a promise that ptr will
only ever point to special places. I can't imagine a situation where I
wouldn't care which of those two interpretations the compiler chooses.
I wasn't suggesting a change in that aspect of the semantics. I was
suggesting not banning compilers from allowing something like

typedef char _Alignas(4) Tfourcc[4];

struct fileheader {
Tfourcc magic;
uint16_t recordSiz;
uint16_t recordCnt;
};

That said, a notation to specify alignment requirements for values of a
pointer object is still a worthwhile thing to do in some situations,
e.g. if the pointer will be passed to alignment sensitive hardware.


Enjoy

Jakob
--
Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com
Transformervej 29, 2860 Søborg, Denmark. Direct +45 31 13 16 10
This public discussion message is non-binding and may contain errors.
WiseMo - Remote Service Management for PCs, Phones and Embedded
Wojtek Lerch
2017-02-28 14:51:44 UTC
Permalink
Raw Message
...
Post by Jakob Bohm
Post by Wojtek Lerch
Consider the declaration
_Alignas(sizeof(int64_t)) int32_t arr[ 10 ];
If the _Alignas() were treated as a type qualifier, this would declare
an array whose each element has the type "_Align(sizeof(int64_t))
int32_t". But it's impossible for all the elements to have the
specified alignment, unless there's padding between them; and in C
arrays never have padding between elements.
The way C11 treats _Align(), the above is not illogical: since the
_Align() applies to the whole array rather than to each element, the
declaration creates an array whose every other element is aligned to a
multiple of an int64.
Okay, for backward compatibility with the C11 definition, it might be
necessary to specify that the _Alignas() notation has a different
"operator priority" than e.g. "volatile", such that the above would
continue to have the same actual semantics.
I think you'd need a new keyword that could parse as a type-qualifier in
the declarator, instead of belonging to the declaration-specifiers like
_Alignas does in C11. This way the C11

_Alignas(N) int *ptr;

could be spelled as

int * _NewAlignAs(N) ptr;

but you could also write

register _NewAlignAs(8) long double *ptr;

to declare a regular pointer variable that points to super-aligned long
doubles.
Post by Jakob Bohm
Having padding between elements can be a good thing, consider this
example
// Assume sizeof(long double) == 10 or 12, as is common on x86
(_Alignas(8) long double) fasttable[10];
// This (or similar) would pad the array such that none of the
// elements would require extra memory bus cycles to access.
Allowing padding between array elements would make pointer arithmetic a
mess, causing a lot of common idioms to fall apart. That's why any
padding that may be needed by an array of structs counts as part of the
struct, not as space between array elements, even if that space could be
useful in a different context:

struct outer {
struct inner {
long a; // assume sizeof(long)==4 and _Alignof(long)==4
char b;
} inner;
char c;
short d; // assume sizeof(short)==2 and _Alignof(short)==2
};

If C allowed padding between array elements, sizeof(struct inner) could
be 5 and sizeof(struct outer) could be 8; but instead, struct inner will
have 3 bytes of padding and struct outer will have another one. I'd
argue that avoiding that kind of waste of space would have been be a
stronger argument for inventing some way to allow padding between array
elements (especially back in the eighties) than your case of
super-aligned scalars is; but apparently it wasn't strong enough. (For
your case, there's a simple workaround -- wrap your long doubles in a
struct that will absorb the necessary padding.)
Post by Jakob Bohm
Post by Wojtek Lerch
Post by Jakob Bohm
Another use is to place such an over-aligned type at the beginning or
other tactical location in a structure declaration, thus causing the
entire structure to be nicely aligned consistently with some other
structures doing the same.
At a minimum, it should be permitted for implementations to treat
_AlignAs() as a type qualifier without violating the standard.
I'm not sure if I disagree or just misunderstand.
If I write
_Alignas(8) int32_t *ptr;
that tells a C11 compiler that I have special requirements on where my
pointer can sit in memory. But you seem to be saying that compilers
should be allowed to interpret it, instead, as a promise that ptr will
only ever point to special places. I can't imagine a situation where I
wouldn't care which of those two interpretations the compiler chooses.
I wasn't suggesting a change in that aspect of the semantics. I was
suggesting not banning compilers from allowing something like
typedef char _Alignas(4) Tfourcc[4];
struct fileheader {
Tfourcc magic;
uint16_t recordSiz;
uint16_t recordCnt;
};
Technically, C11 doesn't ban compilers from allowing this, only requires
that they issue a diagnostic when they see it. :)
Post by Jakob Bohm
That said, a notation to specify alignment requirements for values of a
pointer object is still a worthwhile thing to do in some situations,
e.g. if the pointer will be passed to alignment sensitive hardware.
If you could define a typedef as super-aligned, that would cover it.
Loading...