Abhishek kumar
Abhishek kumar

Reputation: 2676

What is the datatype of a defined constant?

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()?

Upvotes: 7

Views: 9749

Answers (4)

WhozCraig
WhozCraig

Reputation: 66254

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.

Upvotes: 4

CCoder
CCoder

Reputation: 2335

#define is a preprocessor directive. After compilation it does not exist. Instead the corresponding values will be replaced in the code. In this case actual code that is being compiled after macro expansion is

//header stdio.h
//header stdlib.h


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

And yes in this case both 0,300 are integers. !

Upvotes: 1

Daniel Fischer
Daniel Fischer

Reputation: 183978

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.

Upvotes: 3

justin
justin

Reputation: 104718

It's untyped; Just look at it as a textual substitution of your source:

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

Upvotes: 1

Related Questions