What is the preferred way of defining a long integer in C? Are there any compatibility concerns?
long int ln;
or
long ln;
There are no "compatibility concerns", no. They are the exact same type, long is a short form of the type name long int. Just like short is a short form of short int.
It's of course very subjective, but I think most C programmers just use long.
There is no difference between long and long int. You can use what you want. I would rather use long int to remember what you have done.
In addition to #unwind's answer, there is also long double and of course long long int. Long might be useful in other rare corners of implementations (long char?) but it is always a modifier, but int is assumed if there is nothing to modify.
C's syntax has traditionally implied int in many places:
myfunction (i, j)
{
return 6 * i + j;
}
In 1979 implementations on V6 Unix, myfunction() would be interpreted to return type int and both parameters would also be assumed to be int unless further declared:
float myfunction (i, j)
long i; float j;
{
return 6 * i + j;
}
You forgot to mention also signed long and signed long int:)
According to the C Standard
5 Each of the comma-separated multisets designates the same type,
except that for bitfields, it is implementation-defined whether the
specifier int designates the same type as signed int or the same type
as unsigned int
So only for bitfields there is a difference between for example int and signed int
Take into account that you may write for example the following way
const signed const long const int ln;
It is equivalent to
const long ln;
If the company you work for has coding conventions, and they include a requirement on this, you should follow the convention. However, if there is no rule on how you should declare a long int, choose whatever seems best to you.
May I suggest though you use types defined in stdint. For example, long int may be equivalent to int32_t. In a lot of cases its useful to know the bit-width of the variables you're using.
Related
I want to use the method strtoull(...) but do I really have to type out unsigned long long whenever I use it?
The largest integer typedef I could find was uint64_t / size_t but it is not the same as unsigned long long.
I believe unsigned long long takes up to much space. Is there some sort of official and recognized shortcut for it among the community?
Do I have to make my own type? What would be a good name for it? u128int_t or uLLong?
You say you "need a type for unsigned long long int", but unsigned long long int is a type.
Apparently your concern is that the name unsigned long long int is too long to type. You have a point, but defining an alias for it is likely to cause more confusion than it's worth. Every knowledgeable C programmer knows what unsigned long long int means. Nobody knows what your alias means without looking it up, and even then they can't be sure the meaning won't change as the software evolves. If you want to use unsigned long long int, it's best to use unsigned long long int (or unsigned long long).
You can define your own typedef. Remember that typedef doesn't define a new type. It only defines a new name for an existing type.
uint64_t, defined in <stdint.h>, may or may not be an alias for unsigned long long int, depending on the implementation. unsigned long long int is guaranteed to be at least 64 bits, but it could be wider (though I know of no implementations where it's not exactly 64 bits wide). Similarly, uintmax_t is likely to be unsigned long long int, but that's not guaranteed either.
You can define an alias if you like, but I wouldn't recommend it unless you need a name for some type that just happens to be defined as unsigned long long int. If you can give your typedef a name that has meaning within your application, that's probably a good idea. If its only meaning is "a shorter name for unsigned long long, I'd advise against it.
If you need a 64-bit unsigned integer type, uint64_t already exists; just use that. (And if the implementation doesn't provide a type with the required characteristics, then it won't define uint64_t and the error message when you try to use it will tell you that.)
Do I have to make my own type?
You can typedefine whatever name you wish for whatever type (inside the defined naming rules of course), keep in mind that this is only an alias for the original type, hidding predefined types behind typedefs is not consensual, it is legal though.
u128int_t or uLLong?
Taking the above paragraph in consideration, uLLong is perfectly fine. As of today there is no primitive 128 bit wide type in C, u128int_t would be misleading, I would avoid it.
uint64_t is guaranteed to have 64 bits, unsigned long long int is not, it has to have at least 64 bits, but it is not guaranteed by any rule that it should have only that.
Some compilers (for example gcc) support 128bit integers as an extension
example:
__int128_t mul(__int128_t x, __int128_t y)
{
return x * y;
}
https://godbolt.org/z/c8bW1xYdh
When passing 1113355579999 as an argument, the value changes inside the function to 959050335.
Call(main.c):
printf("%d\n", FindCommonDigit(1113355579999, 123457));
Function(ex4.c):
int FindCommonDigit(long int n1, long int n2) { printf("%d\n", n1); }
What's the problem?
worth mentioning that the value changes before getting to the printf.
The decimal number 1113355579999 is too large to be accommodated by a 32-bit integer, which is a common size for type long int, and in fact is the size of long long int in your MSVC environment. On a C implementation that provides 32-bit long ints, that constant has type long long int.
You can pass a long long int to a parameter of type long int, but if the value is too large for long int then the resulting behavior is implementation-defined. Possibly the least-significant 32 bits are retained, which, in the case of your particular number, would result in the number 959050335 (look familiar?). To pass the argument into the function without loss of fidelity, the function parameter must have a type that can accommodate the argument. On a conforming C implementation, long long int will suffice.
Having received the argument correctly, the function must also present it correctly to printf(), else the behavior is undefined. The formatting directive for a long long int expressed in decimal is %lld.
Putting that together, you appear to want this:
int FindCommonDigit(long long int n1, long long int n2) {
printf("%lld\n", n1);
return /* ... something ... */;
}
You do need the function to return an int, else the behavior is again undefined.
Additionally, as #pmg observed in comments, a prototype for that function must be in scope at the point where it is called. That would be this ...
int FindCommonDigit(long long int n1, long long int n2);
... near the top of the source file in which the function is used (i.e. main.c). You can put that directly into the file if you like, but you should consider instead putting the prototype into a header file and #includeing that. The latter is particularly useful if the function will be used in multiple source files.
Note that only long long int is guaranteed to be large enough to store the result of that calculation (or, indeed, the input values you're using).
You will also need to ensure that you use your compiler in a C99-compatible mode (for example, using the -std=gnu99 option to gcc). This is because the long long int type was not introduced until C99
1113355579999 is too large to fit in your platform's long ints.
Maybe I don't find other functions, but all functions that deals with endianness that I find accept only unsigned variable. My question is why (or are there functions that deals with endianness and accept signed variable) ?
List of functions I find : here and here.
Maybe solution is to use these macro ? What is the difference between macro and above function ?
Since endianness is implementation defined, it is safe to assume that you are talking about an implementation and not C standard. Looking at the links you have sent, I think you refer to Linux and GNU C compiler.
Then under this implementation it is safe to first type pun the signed int to unsigned int, change the endianness and type pun it back.
Following is one way of doing it
union signed_unsigned {
signed long a;
unsinged long b;
} converter;
signed long to_convert = .... //whatever value
converter.a = to_convert;
converter.b = htonl(converted.b);
to_convert = converter.a;
You can make this into a macro or a function as you see fit.
As suggested by #underscore_d, the other way to type pun a signed long to unsigned long (and back) is using pointer cast. That is valid in both C and C++ (although in C++ you should use reinterpret_cast rather than C style pointer casts).
You can use the following way to achieve the same.
signed long to_convert = .... //whatever value
unsigned long temp = *(unsinged long*)&to_convert;
temp = htonl(temp);
to_convert = *(signed long*)&temp;
Good day,
I am working in a 16-bit C environment, and I want to convert a float value into its bit sequence such as an integer value.
There are multiple ways I know how to achieve this, one is with a union; such as:
union ConvertFloatToInt
{
float input;
unsigned long output;
};
this will "convert" the floating values into a long value, by reading the same memory area, just interpreting it differently.
union ConvertFloatToInt x;
x.input = 20.00;
result
x.output = 0x41A00000;
Other methods are void pointer casts...
float input = 40.00;
unsigned long output;
void* ptr;
ptr = &input;
output = *(unsigned long*) ptr;
result
output = 0x42200000;
This is the idea of what I am trying to do, however, I want the compiler to do the conversion for me, during build, not during run time.
I need a to insert the converted floating data into a constant (const) unsigned long.
I was thinking of trying to convert the float value into a void, and then the void into the unsigned long.
Something like this: (and yes this is incorrect, you can not cast to a void)
const unsigned long FloatValue = (unsigned long) ((void) ((float) 20.654));
Is there some way to do this? I was thinking maybe something with void pointers, but all void pointers I know of needs a variable, and variables may not be used in the assignment of const values.
Edit
I am using a C90 compiler.
The question is intended in the file scope.
Conclusion
The conclusion was that there is no real solution to this question except when working in the block scope. For which multiple answers were given, and I thank all of you.
My Solution
This is not a good solution, however it solves my problem, but I do not think that this will help many people either.
I created a small program for a demonstration purpose. This is not my projects code, and also not the compiler used in my project (before someone says that this is not a C90 compiler)
The compiler used in the demonstration: gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
typedef union
{
float myfloat;
unsigned long mylong;
} custom_type;
typedef struct
{
int a;
int b;
custom_type typeA;
custom_type typeB;
} my_struct;
const my_struct myobj =
{
1,2,3.84F,4
};
int main(void)
{
printf(":: %f\n", myobj.typeA.myfloat);
printf(":: %ul\n", myobj.typeA.mylong);
return 0;
}
Output
:: 3.840000
:: 1081459343l
This is little bit crude, however it works in the file scope (but generates warnings).
You can do this by type-punning through an anonymous union:
unsigned int i = ((union { float f; unsigned int i; }){5.0}).i;
Note that this initialiser is not a constant expression and so cannot be used at file scope.
Type-punning through a union is specified to be allowed by the standard in a footnote:
c11
6.5.2.3 Structure and union members
95) If the member used to read the contents of a union object is not the same as the member last used to
store a value in the object, the appropriate part of the object representation of the value is reinterpreted
as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type
punning’’). This might be a trap representation.
From a practical point of view, although you cannot use this method to initialise a file-scope constant, you could write an initialisation function that loads the values into file-scope variables at program or module initialisation time.
You're not going to find a portable method that allows you to calculate the values as a compile-time constant expression, because the object representations covered by section 6.2.6 of the standard only apply at run time. Otherwise, a cross-compiler would be required to simulate and not just parametrise the execution environment of its target.
Addendum: this is valid C++, with the condition that the union type must be named:
union u { float f; unsigned int i; };
unsigned int i = u{5.0}.i;
So if you're willing to write in hybrid C/C++ and compile with a C++ compiler, then you can perform the cast at compile time.
You can use a C99 compound literal:
const unsigned long FloatValue =
*(unsigned long *) &(float) {20.654f};
Note that the initializer is not a constant expression so FloatValue can only be declared at block scope and not at file scope.
I am assuming that these floats are constants and therefore you could just write a small program to do it as a one off exercise - generate the output as required. From that small program do a cut'n'paste job into the other code.
If you have a lot of them, why not just write a script to create the appropriate file for C.
You should know somethings about IEEE floating point standards.
http://en.wikipedia.org/wiki/IEEE_floating-point_standard
get the fractions bits and get the exponent bits and process them into a long
You could achieve your purpose by defining a float constant and then a macro:
const float _FloatValue = 20.654;
#define FloatValueL *((unsigned long *) &_FloatValue)
To print a number of type off_t it was recommended to use the following piece of code:
off_t a;
printf("%llu\n", (unsigned long long)a);
Why the format string is not enough?
What will be the problem if it were not casted?
The format string doesn't tell the compiler to perform a cast to unsigned long long, it just tells printf that it's going to receive an unsigned long long. If you pass in something that's not an unsigned long long (which off_t might not be), then printf will simply misinterpret it, with surprising results.
The reason for this is that the compiler doesn't have to know anything about format strings. A good compiler will give you a warning message if you write printf("%d", 3.0), but what can a compiler do if you write printf(s, 3.0), with s being a string determined dynamically at run-time?
Edited to add: As Keith Thompson points out in the comments below, there are many places where the compiler can perform this sort of implicit conversion. printf is rather exceptional, in being one case where it can't. But if you declare a function to accept an unsigned long long, then the compiler will perform the conversion:
#include <stdio.h>
#include <sys/types.h>
int print_llu(unsigned long long ull)
{
return printf("%llu\n", ull); // O.K.; already converted
}
int main()
{
off_t a;
printf("%llu\n", a); // WRONG! Undefined behavior!
printf("%llu\n", (unsigned long long) a); // O.K.; explicit conversion
print_llu((unsigned long long) a); // O.K.; explicit conversion
print_llu(a); // O.K.; implicit conversion
return 0;
}
The reason for this is that printf is declared as int printf(const char *format, ...), where the ... is a "variadic" or "variable-arguments" notation, telling the compiler that it can accept any number and types of arguments after the format. (Obviously printf can't really accept any number and types of arguments: it can only accept the number and types that you tell it to, using format. But the compiler doesn't know anything about that; it's left to the programmer to handle it.)
Even with ..., the compiler does do some implicit conversions, such as promoting char to int and float to double. But these conversions are not specific to printf, and they do not, and cannot, depend on the format string.
The problem is you don't know how big an off_t is. It could be a 64 bit type or a 32 bit type (or perhaps something else). If you use %llu, and do not pass an (unsigned) long long type, you'll get undefined behavior, in practice it might just print garbage.
Not knowing how big it is, the easy way out is to cast it to the biggest reasonable type your system supports, e.g. a unsigned long long. That way using %llu is safe, as printf will receive an unsigned long long type because of the cast.
(e.g. on linux, the size of an off_t is 32 bit by default on a 32 bit machine, and 64 bit if you enable large file support via #define _FILE_OFFSET_BITS=64 before including the relevant system headers)
The signature of printf looks like this:
int printf(const char *format, ...);
The vararg... indicates that anything can follow, and by the rules of C, you can pass anything to printf as long as you include a format string. C simply does not have any constructs to describe any restrictions for the types of objects passed. This is why you must use casts so that the objects passed have exactly the needed type.
This is typical for C, it walks a line between rigidity and trusting the programmer. An unrelated example is that you may use char * (without const) to refer to string literals, but if you modify them, your program may crash.