Risks of adding uint to enum in function call - c

I have a function that returns a float number:
float function(enum value)
I then have an enum
typedef enum
{
a = 0,
b,
c
} myenum;
I want to do the following:
function(a+1);
And I wonder if there are any risks other than the risk of unexpected behaviour if the enum changes. My question might seem dumb but I have to make sure that there are no risks of what I'm doing.
Please don't ask questions on why it's done like this. Because I don't know. I just need to know if it's safe or not.

This is safe. Moreover, the standard guarantees that a+1 is b and a+2 is c in the scenario that you describe:
C99 standard, section 6.7.2.2, part 3: If the first enumerator has no =, the value of its enumeration constant is 0. Each subsequent enumerator with no = defines its enumeration constant as the value of the constant expression obtained by adding 1 to the value of the previous enumeration constant.

It's safe. As you seem to recognise yourself, it's really working against the way enums are intended to work, which is as arbitrary labels. However sometimes you want ordering such that a < b < c. If a = 0 and b = 1 and c = 2 in some firm sense, then you don't want an enum, however, you want a variable of type int.

Related

Programmatically determine if a variable's value was computed at compile time or at run time

Is there a way in C to programmatically determine that variable's value was computed at compile time or at run time?
Example:
const double a = 2.0;
const double b = 3.0;
double c1 = a / b; // done at compile time (constant folding / propagation)
double c2 = *(volatile double*)&a / *(volatile double*)&b; // done at run time
compute_time_t c1_ct = compute_time(c1);
compute_time_t c2_ct = compute_time(c2);
assert(c1_ct == COMPILE_TIME);
assert(c2_ct == RUN_TIME);
In C (as in, defined by the language standard), no, there is no way.
There are however compiler-specific ways using which you can get really close to achieving what you want. The most famous, as #Nate Eldredge notes in the comments, is the builtin function __builtin_constant_p() available in GCC and Clang.
Here's the relevant excerpt from the GCC doc:
Built-in Function: int __builtin_constant_p (exp)
You can use the built-in function __builtin_constant_p to determine if a value is known to be constant at compile time and hence that GCC can perform constant-folding on expressions involving that value. The argument of the function is the value to test. The function returns the integer 1 if the argument is known to be a compile-time constant and 0 if it is not known to be a compile-time constant. A return of 0 does not indicate that the value is not a constant, but merely that GCC cannot prove it is a constant with the specified value of the -O option.
Note that this function does not guarantee to detect all compile-time constants, but only the ones that GCC is able to prove as such. Different optimization levels might change the result returned by this function.
This built-in function is widely used in glibc for optimization purposes (example), and usually the result is only trusted when it's 1, assuming a non-constant otherwise:
void somefunc(int x) {
if (__builtin_constant_p(x)) {
// Perform optimized operation knowing x is a compile-time constant.
} else {
// Assume x is not a compile-time constant.
}
}
Using your own example:
const double a = 2.0;
const double b = 3.0;
double c1 = a / b; // done at compile time (constant folding / propagation)
double c2 = *(volatile double*)&a / *(volatile double*)&b; // done at run time
assert(__builtin_constant_p(c1));
assert(!__builtin_constant_p(c2));
You ask,
Is there a way in C to programmatically determine that variable's
value was computed at compile time or at run time?
No, there is no way to encode such a determination into the source of a strictly conforming C program.
Certainly C does not require values to be tagged systematically in a way that distinguishes among them based on when they were computed, and no C implementation I have ever heard of or imagined does that, so such a determination cannot be based on the values of the expressions of interest. Furthermore, all C function arguments are passed by value, so the hypothetical compute_time() cannot be implemented as a function because values are all it would have to work with.
compute_time() also cannot be a macro, because macros can work only with (preprocessing) tokens, for example the identifiers c1 and c2 in your example code. Those are opaque to the preprocessor; it knows nothing about values attributed to them when they are evaluated as expressions according to C semantics.
And there is no operator that serves the purpose.
Standard C provides no other alternatives, so if the question is about the C language and not any particular implementation of it then that's the end of the story. Moreover, although it is conceivable that a given C implementation would provide your compute_time() or a functional equivalent as an extension, I am unaware of any that do. (However, see #MarcoBonelli's answer, for an example of a similar, but not identical, extension.)

c: can typedef-d enum check for the actual values? [duplicate]

The following text is an excerpt from C Programming Language, 2nd Edition, written by the creator of the C language (so I presume it is correct):
Although variables of enum types may be declared, compilers need not check that what you store in such a variable is a valid value for the enumeration.
I have some doubts:
For what cases in the C language doesn't the compiler check the value of an enum?
enum constants are not checked for some reason. Why not? What are the reasons?
Since enum is not checked by the compiler, is using enum error-prone? Please explain.
An enumeration is like a fancy integer, and it's better than defining a whole load of constants or preprocessor macros as names for the constant values you want to store, because a compiler (or editor) can check that you're using the right names and values to go with the right type. On the other hand, being just an int, there's nothing stopping you putting in a value you didn't make a name for, which is occasionally useful.
They can't be checked in every case. What if you add two numbers together to get the value that's going to be put in the enum-typed variable? It could be any value, generated at runtime, so it can't be checked (without a lot of overhead, at least).
Everything in C is unsafe; there's practically no feature which the compiler can totally prevent you from abusing. enums are safe because they are effective at preventing programmer error and confusion, not because they stop you doing something stupid.
You can do a enum like
enum status {
ST_READY = 1 << 0, /* 1 */
ST_WAIT = 1 << 1, /* 2 */
ST_ERROR = 1 << 2, /* 4 */
ST_HALT = 1 << 3, /* 8 */
ST_ETC = 1 << 4, /* 16 */
};
Then define an object of that type
enum status status;
and set it to the bitwise OR of some 'simple' statuses
status = ST_WAIT | ST_ERROR; /* recoverable error */
Note that the value ST_WAIT | ST_ERROR is 6 and that that value is not part of the enum.
To answer your questions:
C compiler lets the programmer shoot himself in the foot.
C compiler lets the programmer shoot himself in the foot.
C compiler lets the programmer shoot himself in the foot.
At what all cases in C language doesn't the compiler check the value of an enum. [edited]
When you assign to it. Assignment from bare integers is allowed, so you can do:
enum E { A, B } x;
x = 10000;
without compiler error. Also, switches in enums are not check for exhaustiveness.
2)Why enum constants are not checked, for some reasons? What are those reasons?
People like to put integers in them. eg.
enum E { END_OF_EVERYTHING = 5 };
where 0-4 are meant as ordinary values, and 5 is kind of special.
Since enum is not checked by the compiler, using enum is error prone?
Yes. Since enums only have values of the least number of bits that can take all enum values, you can get strange results:
enum E { A = 1, B = -1 };
This enum only contains 2 bits of data (values -2, -1, 0, 1). If you assign 10000 into it, strange things may happen (actually seen).

Bitwise AND operation on boolean values in C [duplicate]

I had the need to code a statement of the form
a = a || expr;
where expr should be evaluated and the result be assigned to a iff a is not set. this relies on the logical OR's short-circuiting capabilities.
The shorter way to write the above would, of course, be
a ||= expr;
but (to my surprise) C does not have logical assignment operators.
So my question is twofold. First, is there a shorter way to write the first statement in standard C (the ternary operator is even worse - a = a ? a : expr requires me to spell out a thrice).
Secondly, why aren't there logical assignments in C? The possible reasons I could think of are:
it makes the grammar harder to parse?
there is some subtlety in handling short-circuiting for these cases?
it was considered superfluous (but isn't that an argument against ALL the operator assignments?)
EDIT
Please unlock this question because:
The question it has been linked to (as a alleged duplicate of) HAS NOT BEEN ANSWERED. The (accepted) answer to that question states that ||= is not present because duplicates the functionality of |=. That is the wrong answer. |= does not short-circuit.
C and C++ are NOT the same languages. I wish to know why C doesn't have it. In fact, the fact that derived languages like C++ and, particularly, Java (which did not suffer from the problems of legacy code as has been suggested in Edmund's answer) makes the question even more interesting.
EDIT 2
It now seems like my original intent was wrong. In the statement a = a || expr (where a is integral and expr returns an integral value, first both a and expr will be implicitly converted to "booleans", and then the "boolean" value will be assigned to a. This will be incorrect — the integral value will be lost. Thanks, Jens and Edmund.
So for the first part of the question, the correct ways, not alternatives :), to code my intention would be:
if (!a) a = expr;
or
a = a ? a : expr;
they should be optimized the same (I think) though personally I would prefer the first one (because it has one less a to type).
However, the second part of the question still remains. The arguments that Jens and Edmund about have given about the ambiguity in a ||= expr apply equally well to a = a || expr. the assignment case can simply be treated as the normal one:
convert a to boolean
if it is true, the value of the entire expression becomes equal to the boolean value of a
otherwise evaluate expr, convert result to boolean, assign to a, and return it
The steps above seem to be the same for both the assignment and normal case.
a ||= expr is problematic due to short circuit evaluation of its equivalent a = a || expr.
To have a ||= expr function like a = a || expr consider OP's assertion:
"In the statement a = a || expr ..., first both a and expr will be implicitly converted to "booleans","
This is not quite correct. expr will not be converted if a evaluates to true. This would make a difference should expr be something like scanf() or rand() or some function that affected the state of the program.
Code such as a ||= scanf("%d", &i) != 1; would only attempt to scan data with a false value in a. Although it would be possible to extend the language this way, additional short-circuit operators to the current set of || and && would likely cause more coding problems than clear simplifications.
On the other hand: A quick, if obfuscated, way to write code where functions return non-zero codes on error.
// Perform functions until an error occurs.
bool error = foo1();
error &&= foo2(); // Only valid if C was extended with &&=
error &&= foo3();
Because the return type of operators || and && is not the same as type of their left argument.
The return type of || and && is always int1, while the left argument may be any integral, floating point or pointer type. The operands also don't have to be of the same type. Therefore defining x ||= y as x = x || y and x &&= y as x = x && y as would be consistent with other augmented assignments would not be able to store the result in the argument for most types.
You could come up with other definitions, e.g. x ||= y as if(!x) x = y and x &&= y as if(!y) x = y, but that would not be exactly obvious and it is not that useful, so it was not included.
1In C++ it is bool.
I guess the simple answer is that || is a boolean operator: and in C, a "boolean" is 0 or 1. The operands are implicitly converted to booleans (I have not checked that that's what the spec actually says, but it's how C behaves), and the result is a boolean.
Altering the semantics to support this pattern may well be feasible -- until someone relies on || doing what it's always done.
I cannot find any particular reason, why the operators don't exist (in C99).
So the only reason I can find is, that there was no boolean type in C89, and those boolean operators were intended to be solely used in if's.
Example:
int i = 5;
/* This should not make any difference,
since or'ing with false, shouldn't change
the value... dib di dib diddy...*/
i ||= 0; /* Actually: i = i || 0, which gives 'true' */
i is now '1'', which for most people is pretty counter intuitive.
This operator obviously doesn't bring any clearence or coding improvement without the boolean type, that would make sence being or'd with another one.
In my opinion, the implementation of a ||= b; as if(!a) a = b; would be pretty straightforward and has aleardy been implemented by e.g. Lua.
So you're question seems to be a bit, why C has been designed the way it has been designed.
If this question was about C++, you could for example ask Bjarne Stroustrup and ask him, what had went into him. Since this is not the case, this seems to me to be kind of a dead end, because the standard has been written quite some time ago and you cannot really ask people anymore, why the h***.
On the other hand, this incomplete operator set should (in my opinion) aleardy have been made whole using a similar notation than yours, since in my opinion, there is no reason against it.
I hope I could help a little.
One simple explanation is this.
bool resultsComputeAll = false;
bool resultsUntilFirst = false;
for (int i = 0; i < 10; ++i) {
resultsComputeAll = compute(i) || resultsComputeAll;
resultsUntilFirst = resultsUntilFirst || compute(i);
}
Which one would be result ||= compute(i)? It's ambiguous so it's better to not define.

C/GL: Using -1 as sentinel on array of unsigned integers

I am passing an array of vertex indices in some GL code... each element is a GLushort
I want to terminate with a sentinel so as to avoid having to laboriously pass the array length each time alongside the array itself.
#define SENTINEL ( (GLushort) -1 ) // edit thanks to answers below
:
GLushort verts = {0, 0, 2, 1, 0, 0, SENTINEL};
I cannot use 0 to terminate as some of the elements have value 0
Can I use -1?
To my understanding this would wrap to the maximum integer GLushort can represent, which would be ideal.
But is this behaviour guaranteed in C?
(I cannot find a MAX_INT equivalent constant for this type, otherwise I would be using that)
If GLushort is indeed an unsigned type, then (GLushort)-1 is the maximum value for GLushort. The C standard guarantees that. So, you can safely use -1.
For example, C89 didn't have SIZE_MAX macro for the maximum value for size_t. It could be portably defined by the user as #define SIZE_MAX ((size_t)-1).
Whether this works as a sentinel value in your code depends on whether (GLushort)-1 is a valid, non-sentinel value in your code.
GLushort is an UNSIGNED_SHORT type which is typedefed to unsigned short, and which, although C does not guarantee it, OpenGL assumes as a value with a 2^16-1 range (Chapter 4.3 of the specification). On practically every mainstream architecture, this somewhat dangerous assumption holds true, too (I'm not aware of one where unsigned short has a different size).
As such, you can use -1, but it is awkward because you will have a lot of casts and if you forget a cast for example in an if() statement, you can be lucky and get a compiler warning about "comparison can never be true", or you can be unlucky and the compiler will silently optimize the branch out, after which you spend days searching for the reason why your seemingly perfect code executes wrong. Or worse yet, it all works fine in debug builds and only bombs in release builds.
Therefore, using 0xffff as jv42 has advised is much preferrable, it avoids this pitfall alltogether.
I would create a global constant of value:
const GLushort GLushort_SENTINEL = (GLushort)(-1);
I think this is perfectly elegant as long as signed integers are represented using 2's complement.
I don't remember if thats guaranteed by the C standard, but it is virtually guaranteed for most CPU's (in my experience).
Edit: Appparently this is guaranteed by the C standard....
If you want a named constant, you shouldn't use a const qualified variable as proposed in another answer. They are really not the same. Use either a macro (as others have said) or an enumeration type constant:
enum { GLushort_SENTINEL = -1; };
The standard guarantees that this always is an int (really another name of the constant -1) and that it always will translate into the max value of your unsigned type.
Edit: or you could have it
enum { GLushort_SENTINEL = (GLushort)-1; };
if you fear that on some architectures GLushort could be narrower than unsigned int.

Difference and definition of literal and symbolic constants in C?

I am having trouble getting to grips with the definition and uses of symbolic and literal constants and I was wondering if you anyone could explain them and highlight their differences. Thanks!
A literal constant is a value typed directly into your program wherever it is needed. For example
int tempInt = 10;
tempInt is a variable of type int; 10 is a literal constant. You can't assign a value to 10, and its value can't be changed. A symbolic constant is a constant that is represented by a name, just as a variable is represented. Unlike a variable, however, after a constant is initialized, its value can't be changed.
If your program has one integer variable named students and another named classes, you could compute how many students you have, given a known number of classes, if you knew there were 15 students per class:
students = classes * 15;
A symbol is something that the compiler deals with. The compiler treats a const pretty much the way it treats a variable. On the other hand, a #define is something the compiler is not even aware of, because the precompiler transforms it into its value. It's like search-and-replace. If you do
#define A 5
and then
b += A;
The precompiler translates it into
b += 5;
and all the compiler sees is the number 5.
(Borrowing from earlier posts)
A literal constant is a value typed directly into your program wherever it is needed. For example
int breakpoint = 10;
The variable breakpoint is an integer (int); 10 is a literal constant. You can't assign a value to 10, and its value can't be changed. Unlike a variable, a constant can't be changed after it is assigned a value (initialized).
A symbol is something that the compiler deals with. In this example, TEN is a symbolic constant created using the #define function. A #define is something the compiler is not even aware of, because the precompiler transforms it into its assigned (defined) value. The precompiler searches out and replaces every symbol constant inside your program with a value.
#define TEN 10 /* These two lines of code become one... */
breakpoint += TEN; /* after running through the precompiler */
The precompiler translates it into
Breakpoint += 10;
The compiler never sees TEN but only its assigned value, 10. Why is this useful? What if the breakpoint is changed to 11. Rather than looking through the entire program and changing every variable definition to the new value that was set using a literal constant, 10, change the definition of a single symbol constant... TEN to 11 and let the precompiler do the changes for you.
I think what you mean is that a literal constant is a primitive expression like "string" or 2 or false, while a symbolic one is when you give it a name, like const int MagicNumber = 42. Both can be used as expressions, but you can refer to the latter with a name. Useful if you use the same constant from many places.

Resources