Using multiplied macro in array declaration - c

I know the following is valid code:
#define SOMEMACRO 10
int arr[SOMEMACRO];
which would result as int arr[10].
If I wanted to make an array 2x size of that (and still need the original macro elsewhere), is this valid code?
#define SOMEMACRO 10
int arr[2 * SOMEMACRO];
which would be int arr[2 * 10] after precompilation. Is this still considered as constant expression by the compiler?
After a quick look it seems to work, but is this defined behavior?

Yes it will work.MACRO will be placed as it is at compilation so a[2*SOMEMACRO] will become a[2*10] which is perfectly valid.
To check what is preprocessed you can use cc -E foo.c option

Is this still considered as constant expression by the compiler?
Yes. That's the difference between a constant expression and a literal: a constant expression need not be a single literal, bit it can be any expression of which the value can be computed at compile time (i. e. a combination of literals or other constant expressions).
(Just for the sake of clarity: of course literals are still considered constant expressions.)
However, in C, the size of the array need not be a compile-time constant. C99 and C11 supports variable-length arrays (VLAs), so
size_t sz = // some size calculated at runtime;
int arr[sz];
is valid C as well.

Yes you can use this expression. It will not result in UB.
Note that an array subcript may be an integer expression:
#define i 5
#define j 4
int a[i+j*10] = 0;
The value of of subscript i+j*10 will be calculated during compilation.

yes, as long as it a valid number it's a constant expression.
and if you say it worked then you know the compiler worked just fine with it.
as you know we can't do
int x;
scanf("%d", &x);
int arr[2 * x];
because that's no a constant number. but what you've written is a constant number, so you're good to go

Related

What's the correct way to use scanf_s in using string arrays?

char array1[10];
scanf_s("%9s", array1, (unsigned)_countof(array1);
What's mean of (unsigned)_countof(array1)?
and what's different from use scanf_s("%9s", array1, sizeof(array1);?
both worked, but I want to understand about it more surely
What's the correct way to use scanf_s in using string arrays?
scanf_s() with "%9s" is not for string arrays. It is for reading text and saving as a single string, which is a character array with a null character.
Its proper use is complicated by MSVC expects a different type in the count argument than C11. In C11 and later, scanf_s() is an optional function of the standard library and lacks wide acceptance.
// MSVC - type unsigned expected, hence the cast.
scanf_s("%9s", array1, (unsigned)_countof(array1);
// C11 - type size_t expected
scanf_s("%9s", array1, sizeof array1 / sizeof array1[0]);
Proper use of either obliges code to check the return value of scanf_s()
if (1 == scanf_s("%9s", ...)) Success();
else Fail();
What's mean of (unsigned)_countof(array1)?
_countof() is an MSVC macro equivalent to (sizeof(array) / sizeof(array[0])). When passed an array, it returns the count of elements in the array as type size_t. Casting to unsigned gets the expected type as with MSVC scanf_s(). The value may truncate due to the cast - a rare issue with huge arrays.
what's different from use scanf_s("%9s", array1, sizeof(array1));?
The expected type of sizeof(array1) is size_t and not unsigned as expected in MSVC - leading to undefined behavior. When size_t is as unsigned, that is OK, else a real problem.
The conceptual value is wrong. It should be the array element count, not the byte size of the array. Either OK here as sizeof(char)==1, yet wrong if code moved to say using wide characters.
both worked
Code is not portable. It may have "worked" in OP's case, but lacks portability.
Consider alternatives to scanf_s(), scanf() like fgets().
sizeof and _countof are different.
(edit:) In this case you should use countof.
sizeof is an operator in C that returns the memory size occupied by a variable, in bytes.
In this case, array1 is an array of 10 chars, so it's size is ten times the size of a char, and sizeof(char) is 1 byte. So the value of sizeof(array1) is 10 * 1 = 10 bytes.
Note that in C you can use sizeof on any variable (e.g. sizeof(array1)) or on any type (e.g. sizeof(int)).
_countof is a macro (only available on Microsoft platforms) that gives you the number of elements declared in an array variable. In this case your array1 variable has 10 elements, so _countof(array1) will be 10.
Now in your precise case this happens to be the same result because the size of each char is 1, but this wouldn't be the same if, for example, your variable was an array of ints.
int array2[10];
sizeof(array2); // = 40
_countof(array2); // = 10
An int is (usually) 4 bytes, so an array of 10 ints will have a size of 10*4 = 40 bytes. On the other hand, _countof will just count how many elements are declared in the array, and still return 10.
In fact, we can see that the definition of _countof is litterally sizeof(array) divided by sizeof(array[0]), that is, the size of an individual element.
Since scanf_s with "%s" expects a number of items, you should be using _countof. (edit).
You might also want to be careful with sizeof (and _countof) on arrays, and avoid using them on pointers. Also be aware that _countof will not work outside of Visual Studio. See these related answers.
This question is compiler based, GCC 11.1.0 on Arch Linux does not have functions like scanf_s and _countof. These functions/macros might be valid in Windows.
I read some docs on Microsoft docs. So, _countof is a macro which calls sizeof() internally and scanf_s is similar to scanf in standard C17.
What's mean of (unsigned)_countof(array1)? and what's different from use scanf_s("%9s", array1, sizeof(array1);? both work, but I want to understand about it more surely
Here the macro _countof is counting the length of the stack stored array, which in this case is 10.
_countof macro expands to:
#define _countof(x) (sizeof(x) / sizeof(x[0]))
// the operation goes for `array1` like this:
// 10 * 1 byte / 1 byte
// 1 byte is the sizeof char
// hence, 10 is returned as the result of the above operation
And (unsigned) is just type casting the value of the above operation.
NOTE: As _countof is calling sizeof() do not use this inside a function the get the length of an array. Because sizeof(arr_ptr) will return the size of pointer which is 8 bytes in my case (x86_64 architecture).
Conclusion:
There no _countof is just calling sizeof(). I would like to suggest you to use sizeof and scanf functions because they are cross-platform and portable throughout the C standards.

the size of dynamically allocated array in C [duplicate]

This question already has answers here:
Behavior of sizeof on variable length arrays (C only)
(2 answers)
Closed 5 years ago.
I know that this question has been asked before, but my question is more specific,
here is the code:
#include <stdio.h>
#include <time.h> /* must be included for the time function */
main()
{
time_t t = time(NULL);
srand((unsigned) t);
int i = rand();
int a[i];
printf("%d\n", i); /* ouptut: 18659 */
printf("%d\n", sizeof a); /* output: 74636 */
}
I compiled this code using gcc and -ansi option to restrict it to recognize the ANSI C only.
I know that there is no way that the compiler could know at compile-time the size of the array because it's determined randomly at run-time.
Now my question is is the value returned by sizeof is just a random value, or it has a meaning?
The sizeof operator is evaluated at compile time for most operands. In the case of a VLA, it is evaluated at runtime.
From section 6.5.3.4 of the C standard:
2 The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The
size is determined from the type of the operand. The result is an
integer. If the type of the operand is a variable length array type,
the operand is evaluated; otherwise, the operand is not evaluated and
the result is an integer constant
So the size returned by sizeof is the size in bytes of the VLA. In your example, that would be i * sizeof(int)
The value returned by sizeof is a pseudo-random value that has a meaning:
The value represents the size of VLA a, in bytes
It is random only in the sense that the number of array elements is determined by a call to rand.
It appears that sizeof(int) on your system is 4, because the number returned by sizeof is four times the number of elements in the array.
Note: One of the consequences of allowing VLAs in C99 is that sizeof is no longer a purely compile-time expression. When the argument of sizeof operator is a VLA, the result is computed at run-time.
From the gcc manual
The -ansi option does not cause non-ISO programs to be rejected gratuitously. For that, -Wpedantic is required in addition to -ansi.
is the value returned by sizeof is just a random value, or it has a meaning?
It does have a meaning, as 74636 / 18659 = 4, which apparently is the size of int on your machine.
So sizeof (which will be computed at run-time instead of compile-time since the argument is a VLA), will return the size of array a in bytes, which is the number of ints it contains (in other words i or 18659) multiplied by the size of int, which is 4 on your machine.
As i (the result of rand) is random, you can consider that the value of sizeof will be random too in that sense.

will ~ operator change the data type?

When I read someone's code I find that he bothered to write an explicite type cast.
#define ULONG_MAX ((unsigned long int) ~(unsigned long int) 0)
When I write code
1 #include<stdio.h>
2 int main(void)
3 {
4 unsigned long int max;
5 max = ~(unsigned long int)0;
6 printf("%lx",max);
7 return 0;
8 }
it works as well. Is it just a meaningless coding style?
The code you read is very bad, for several reasons.
First of all user code should never define ULONG_MAX. This is a reserved identifier and must be provided by the compiler implementation.
That definition is not suitable for use in a preprocessor #if. The _MAX macros for the basic integer types must be usable there.
(unsigned long)0 is just crap. Everybody should just use 0UL, unless you know that you have a compiler that is not compliant with all the recent C standards with that respect. (I don't know of any.)
Even ~0UL should not be used for that value, since unsigned long may (theoretically) have padding bits. -1UL is more appropriate, because it doesn't deal with the bit pattern of the value. It uses the guaranteed arithmetic properties of unsigned integer types. -1 will always be the maximum value of an unsigned type. So ~ may only be used in a context where you are absolutely certain that unsigned long has no padding bits. But as such using it makes no sense. -1 serves better.
"recasting" an expression that is known to be unsigned long is just superfluous, as you observed. I can't imagine any compiler that bugs on that.
Recasting of expression may make sense when they are used in the preprocessor, but only under very restricted circumstances, and they are interpreted differently, there.
#if ((uintmax_t)-1UL) == SOMETHING
..
#endif
Here the value on the left evalues to UINTMAX_MAX in the preprocessor and in later compiler phases. So
#define UINTMAX_MAX ((uintmax_t)-1UL)
would be an appropriate definition for a compiler implementation.
To see the value for the preprocessor, observe that there (uintmax_t) is not a cast but an unknown identifier token inside () and that it evaluates to 0. The minus sign is then interpreted as binary minus and so we have 0-1UL which is unsigned and thus the max value of the type. But that trick only works if the cast contains a single identifier token, not if it has three as in your example, and if the integer constant has a - or + sign.
They are trying to ensure that the type of the value 0 is unsigned long. When you assign zero to a variable, it gets cast to the appropriate type.
In this case, if 0 doesn't happen to be an unsigned long then the ~ operator will be applied to whatever other type it happens to be and the result of that will be cast.
This would be a problem if the compiler decided that 0 is a short or char.
However, the type after the ~ operator should remain the same. So they are being overly cautious with the outer cast, but perhaps the inner cast is justified.
They could of course have specified the correct zero type to begin with by writing ~0UL.

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.

Confused about C macro expansion and integer arithmetic [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
A riddle (in C)
I have a couple of questions regarding the following snippet:
#include<stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int d;
for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
printf("%d\n",array[d+1]);
return 0;
}
Here the output of the code does not print the array elements as expected. But when I add a typecast of (int) the the macro definition of ELEMENTS as
#define TOTAL_ELEMENTS (int) (sizeof(array) / sizeof(array[0]))
It displays all array elements as expected.
How does this typecast work?
Based on this I have few questions:
Does it mean if I have some macro definition as:
#define AA (-64)
by default in C, all constants defined as macros are equivalent to signed int.
If yes, then
But if I have to forcibly make some constant defined in a macro behave as an unsigned int is there any constant suffix than I can use (I tried UL, UD neither worked)?
How can I define a constant in a macro definition to behave as unsigned int?
Look at this line:
for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
In the first iteration, you are checking whether
-1 <= (TOTAL_ELEMENTS-2)
The operator size_of returns unsigned value and the check fails (-1 signed = 0xFFFFFFFF unsigned on 32bit machines).
A simple change in the loop fixes the problem:
for(d=0;d <= (TOTAL_ELEMENTS-1);d++)
printf("%d\n",array[d]);
To answer your other questions: C macros are expanded text-wise, there is no notion of types. The C compiler sees your loop as this:
for(d=-1;d <= ((sizeof(array) / sizeof(array[0]))-2);d++)
If you want to define an unsigned constant in a macro, use the usual suffix (u for unsigned, ul for unsigned long).
sizeof returns the number of bytes in unsigned format. That's why you need the cast.
See more here.
Regarding your question about
#define AA (-64)
See Macro definition and expansion in the C preprocessor:
Object-like macros were conventionally used as part of good programming practice to create symbolic names for constants, e.g.
#define PI 3.14159
... instead of hard-coding those numbers throughout one's code. However, both C and C++ provide the const directive, which provides another way to avoid hard-coding constants throughout the code.
Constants defined as macros have no associated type. Use const where possible.
Answering just one of your sub-questions:
To "define a constant in a macro" (this is a bit sloppy, you're not defining a "constant", merely doing some text-replacement trickery) that is unsigned, you should use the 'u' suffix:
#define UNSIGNED_FORTYTWO 42u
This will insert an unsigned int literal wherever you type UNSIGNED_FORTYTWO.
Likewise, you often see (in <math.h> for instance) suffices used to set the exact floating-point type:
#define FLOAT_PI 3.14f
This inserts a float (i.e. "single precision") floating-point literal wherever you type FLOAT_PI in the code.

Resources