Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the datatype of a defined constant?

Tags:

c

I was trying this code.

#include <stdio.h>
#include <stdlib.h>
#define LOWER 0
#define UPPER 300

int main()
{
    printf("%d %f",LOWER,UPPER);
    return 0;
}

I read some of the answers and it says that defined constants don't have a type and are not allocated any memory. Then why is it giving errors if i specify different type specifiers in printf()?

like image 416
Abhishek kumar Avatar asked Oct 31 '12 16:10

Abhishek kumar


People also ask

What are defined constants?

constant. noun. Definition of constant (Entry 2 of 2) : something invariable or unchanging: such as. a : a number that has a fixed value in a given situation or universally or that is characteristic of some substance or instrument.

What type is a #define in C?

#define in C is a directive which is used to #define alias.

What is a defined constant in C?

A constant is a name given to the variable whose values can't be altered or changed. A constant is very similar to variables in the C programming language, but it can hold only a single variable during the execution of a program.

What are the two types of constant variable?

Overview. Variables having fixed values that don't change and cannot be changed throughout the execution of the program once initialized are called Constants. There are mainly two types of constants: primary and secondary.


2 Answers

In your example, both are pushed into the variadic parameter list of printf as int values. This can cause problems with the format flags in the format string of printf() do not match the underlying type. Refer to this post for reasons why undefined behavior can ensue.

As hideous as it seems, one way to know you can get what you're looking for in this printf is to do this:

#include <stdio.h>
#include <stdlib.h>
#define LOWER 0
#define UPPER 300

int main()
{
    printf("%d %f", (int)LOWER, (float)UPPER);
    return 0;
}

In both cases, these are preprocessor macros that are substituted before compilation. Note that if UPPER cannot be promoted to a float you will receive a compiler error, which is a good thing. if it can be, it will be, and the printf() will find the bytes it needs to print what it wants. The same is true for int and LOWER respectively. The above printf will degenerate to this after preprocessing:

printf("%d %f", (int)0, (float)300);

Now imagine your macros were instead declared as such:

#define LOWER 100.0
#define UPPER 300.0

The original printf() will present as thus after preprocessing:

printf("%d %f", 100.0, 300.0);

which may seem right, but is that 100.0 float really going to be properly excised by the %d format string handler in printf()? Make sure. Doing what we did before:

printf("%d %f", (int)LOWER, (float)UPPER);

now preprocesses to:

printf("%d %f", (int)100.0, (float)300.0);

You may get a compiler warning on the float-to-int cast, you may not. Unless you want to roll the dice that what you're passing is sized to what is byte-size-expected by things like printf() you need to be damn-sure everything matches. This can get especially frustrating when the format specifier expects one thing, something different is passed in, and yet it appears to all work fine, but only on some platforms mysteriously:

printf("%ld\n", UPPER);

This may "work", but if it does it is only because a long int and a int are the same size on your platform. Move this code to a platform where long int and int are different bit-widths and its UB all the way.

Bottom line: If you're passing preprocessor macros into variadic parameter lists for things like printf() that have size expectations for the data being pushed (as specified by the format string for example) you better make sure what you're pushing is what is expected.

like image 177
WhozCraig Avatar answered Nov 03 '22 00:11

WhozCraig


In this case, the type is the type of the literal constants. Both 0 and 300 are integer constants that fit in an int, so their type is int.

like image 22
Daniel Fischer Avatar answered Nov 03 '22 01:11

Daniel Fischer