#include<stdio.h>
int main()
{
printf("\nsize of int : %d", sizeof int);
return 0;
}
is returning error
error: expected expression before ‘int’
while compiling with C
and
expected primary-expression before ‘int’
while compiling with C++, but the following codes works just fine.
#include<stdio.h>
int main()
{
int b;
printf("\nsize of int : %d", sizeof b);
;
return 0;
}
Why is it so? What is the difference in both the cases?
sizeof needs parentheses when used with a type. They're optional with an expression.
Your code would then become:
printf("\nsize of int : %zu", sizeof(int));
Thanks to #Grijesh, I've also used the right format specifier for size_t. If this format specifier causes problems (likely related to Windows), the next best would probably be %lu.
You forgot the brackets(). When you are using sizeof with a type you need brackets. Try this:
printf("\nsize of int : %zu", sizeof(int));
You may also use the format specifier %lu when %zu is not available in microsoft compilers.
The sizeof operator is used to determine the amount of space a designated datatype would occupy in memory. To use sizeof, the keyword "sizeof" is followed by a type name or an expression (which may be merely a variable name). If a type name is used, it must always be enclosed in parentheses, whereas expressions can be specified with or without parentheses.
char c;
printf("%zu,%zu\n", sizeof c, sizeof (int));
Related
I just found out that this is illegal in C++ (but legal in C):
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_LENGTH(A) (sizeof(A) / sizeof(A[0]))
int accumulate(int n, const int (*array)[])
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += (*array)[i];
}
return sum;
}
int main(void)
{
int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));
return 0;
}
It compiles without problems using gcc -std=c89 -pedantic but fails to compile using g++. When I try to compile it using g++ I get these error messages:
main.cpp:5:37: error: parameter 'array' includes pointer to array of unknown bound 'int []'
int accumulate(int n, int (*array)[])
^
main.cpp: In function 'int main()':
main.cpp:18:50: error: cannot convert 'int (*)[9]' to 'int (*)[]' for argument '2' to 'int accumulate(int, int (*)[])'
printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));
I have been using this in my C code for a long time and I had no idea that it was illegal in C++. To me this seems like a useful way to document that a function takes an array whose size is not known before hand.
I want to know why this is legal C but invalid C++. I also wonder what it was that made the C++ committee decide to take it away (and breaking this compatibility with C).
So why is this legal C code but illegal C++ code?
Dan Saks wrote about this in 1995, during the lead up to C++ standardisation:
The committees decided that functions such as this, that accept a
pointer or reference to an array with unknown bound, complicate
declaration matching and overload resolution rules in C++. The
committees agreed that, since such functions have little utility and
are fairly uncommon, it would be simplest to just ban them. Hence, the
C++ draft now states:
If the type of a parameter includes a type of the form pointer to
array of unknown bound of T or reference to array of unknown bound of
T, the program is ill-formed.
C++ doesn't have C's notion of "compatible type". In C, this is a perfectly valid redeclaration of a variable:
extern int (*a)[];
extern int (*a)[3];
In C, this is a perfectly valid redeclaration of the same function:
extern void f();
extern void f(int);
In C, this is implementation-specific, but typically a valid redeclaration of the same variable:
enum E { A, B, C };
extern enum E a;
extern unsigned int a;
C++ doesn't have any of that. In C++, types are either the same, or are different, and if they are different, then there is very little concern in how different they are.
Similarly,
int main() {
const char array[] = "Hello";
const char (*pointer)[] = &array;
}
is valid in C, but invalid in C++: array, despite the [], is declared as an array of length 6. pointer is declared as a pointer to an array of unspecified length, which is a different type. There is no implicit conversion from const char (*)[6] to const char (*)[].
Because of that, functions taking pointers to arrays of unspecified length are pretty much useless in C++, and almost certainly a mistake on the part of the programmer. If you start from a concrete array instance, you almost always have the size already, so you cannot take its address in order to pass it to your function, because you would have a type mismatch.
And there is no need for pointers to arrays of unspecified length in your example either: the normal way to write that in C, which happens to also be valid in C++, is
int accumulate(int n, int *array)
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += array[i];
}
return sum;
}
to be called as accumulate(ARRAY_LENGTH(a), a).
I just found out that this is illegal in C++ (but legal in C):
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_LENGTH(A) (sizeof(A) / sizeof(A[0]))
int accumulate(int n, const int (*array)[])
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += (*array)[i];
}
return sum;
}
int main(void)
{
int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));
return 0;
}
It compiles without problems using gcc -std=c89 -pedantic but fails to compile using g++. When I try to compile it using g++ I get these error messages:
main.cpp:5:37: error: parameter 'array' includes pointer to array of unknown bound 'int []'
int accumulate(int n, int (*array)[])
^
main.cpp: In function 'int main()':
main.cpp:18:50: error: cannot convert 'int (*)[9]' to 'int (*)[]' for argument '2' to 'int accumulate(int, int (*)[])'
printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));
I have been using this in my C code for a long time and I had no idea that it was illegal in C++. To me this seems like a useful way to document that a function takes an array whose size is not known before hand.
I want to know why this is legal C but invalid C++. I also wonder what it was that made the C++ committee decide to take it away (and breaking this compatibility with C).
So why is this legal C code but illegal C++ code?
Dan Saks wrote about this in 1995, during the lead up to C++ standardisation:
The committees decided that functions such as this, that accept a
pointer or reference to an array with unknown bound, complicate
declaration matching and overload resolution rules in C++. The
committees agreed that, since such functions have little utility and
are fairly uncommon, it would be simplest to just ban them. Hence, the
C++ draft now states:
If the type of a parameter includes a type of the form pointer to
array of unknown bound of T or reference to array of unknown bound of
T, the program is ill-formed.
C++ doesn't have C's notion of "compatible type". In C, this is a perfectly valid redeclaration of a variable:
extern int (*a)[];
extern int (*a)[3];
In C, this is a perfectly valid redeclaration of the same function:
extern void f();
extern void f(int);
In C, this is implementation-specific, but typically a valid redeclaration of the same variable:
enum E { A, B, C };
extern enum E a;
extern unsigned int a;
C++ doesn't have any of that. In C++, types are either the same, or are different, and if they are different, then there is very little concern in how different they are.
Similarly,
int main() {
const char array[] = "Hello";
const char (*pointer)[] = &array;
}
is valid in C, but invalid in C++: array, despite the [], is declared as an array of length 6. pointer is declared as a pointer to an array of unspecified length, which is a different type. There is no implicit conversion from const char (*)[6] to const char (*)[].
Because of that, functions taking pointers to arrays of unspecified length are pretty much useless in C++, and almost certainly a mistake on the part of the programmer. If you start from a concrete array instance, you almost always have the size already, so you cannot take its address in order to pass it to your function, because you would have a type mismatch.
And there is no need for pointers to arrays of unspecified length in your example either: the normal way to write that in C, which happens to also be valid in C++, is
int accumulate(int n, int *array)
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += array[i];
}
return sum;
}
to be called as accumulate(ARRAY_LENGTH(a), a).
Consider the following data structure:
union LambdaBox {
struct {
uint64_t full;
char lambda[];
} data;
char padding[64];
};
The size of the member variable full is clearly known at compile time.
How can I refer to it directly without first creating an object of type LambdaBox?
More specifically, I am trying to write an expression (evaluated at compile-time) that is semantically equivalent to the third statement below.
int main(){
// This works
printf("The total size allowed is %zu\n", 56L);
// This also works
printf("The total size of LambdaBox is %zu\n", sizeof(LambdaBox));
// What is the correct syntax for the semantic meaning of the following line?
printf("The total size allowed is %zu\n", sizeof(LambdaBox) -
sizeof(LambdaBox::data::full);
}
Use decltype (C++11 and later):
sizeof(LambdaBox) - sizeof decltype(LambdaBox::data)::full
On coliru: http://coliru.stacked-crooked.com/a/b566a890b4143838
You can avoid the need for decltype by naming the anonymous type of data.
You can use the fact that the sizeof-operand is always unevaluated to avoid temporaries even if you cannot use decltype (Works even on ancient compilers):
sizeof(LambdaBox) - sizeof LambdaBox().data.full
On coliru: http://coliru.stacked-crooked.com/a/14bcbd6995c9dd8c
The direct way:
sizeof(LambdaBox) - sizeof LambdaBox::data.full
On coliru: http://coliru.stacked-crooked.com/a/f984d8e9462ca2c2
Be aware that flexible array-members are a C99 feature not even in C++14 though (GCC and clang accept it as an extension).
Here is one workaround I found which does not use C++11 features, which my compiler g++ 4.4.7 does not fully support.
#include <stdint.h>
#include <stdio.h>
union LambdaBox {
struct {
uint64_t full;
char lambda[];
} data;
char padding[64];
static uint64_t getMaxSize() {
return sizeof(LambdaBox) - sizeof(data.full);
}
};
int main(){
printf("The total size allowed is %zu\n", 56L);
printf("The total size of LambdaBox is %zu\n", sizeof(LambdaBox));
printf("The total size allowed is %zu\n", LambdaBox::getMaxSize());
}
This code on array of structures is working but according to my understanding it shoudn't.
Code:
#include<stdio.h>
#include<string.h>
int main()
{
struct virus {
char signature[25];
char status[20];
int size;
} v[2] = {
"Yankee Doodle", "Deadly", 1813,
"Dark Avenger", "Killer", 1795
};
for(int i=0;i<=1;i++) {
printf("%s %s\n", &v[i].signature, &v[i].status);
}
return 0;
}
According to me, when we try to access the members of a structure using the address of an instance of the structure, we must use the -> operator rather than the . operator. I know that we do it only in case a pointer,but as far as I know, array is functionally equivalent to a pointer. Please help me where I am going wrong with my concepts. And pardon my silly question, because I am just a beginner.
It should not according to Operator Precedence. [] has higher precedence than ., and . has higher precedence than &. So &v[i].signature is equivalent to & ( (v[i]).signature). So first the ith item is taken from v, then it's signature member is accessed, which is a character array, and then & is applied which gives the address of the character array.
It works in VS, but this is not standard behavior.
It doesn't really work. You probably expected &v[i].signature to be (&v[i]).signature (which should have been (&v[i])->signature), but it's actually &(v[i].signature), of type char (*)[25]. If the program still produces the expected output, then that's purely by chance.
GCC would have told you this even without -Wall:
$ gcc -c a.c
a.c: In function ‘main’:
a.c:18:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[25]’ [-Wformat=]
printf("%s %s\n",&v[i].signature,&v[i].status);
^
a.c:18:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘char (*)[20]’ [-Wformat=]
It's working because:
&v[i].signature == &v[i] == v->signature
(&v).signature == v->signature
You have taken the address using & and dereferenced using [].
I have a struct like this
typedef struct _somestruct {
int a;
int b;
}SOMESTRUCT,*LPSOMESTRUCT;
I am creating an object for the struct and trying to print it's address like this
int main()
{
LPSOMESTRUCT val = (LPSOMESTRUCT)malloc(sizeof(SOMESTRUCT));
printf("0%x\n", val);
return 0;
}
..and I get this warning
warning C4313: 'printf' : '%x' in
format string conflicts with argument
1 of type 'LPSOMESTRUCT'
So, I tried to cast the address to int like this
printf("0%x\n", static_cast<int>(val));
But I get this error:
error C2440: 'static_cast' : cannot
convert from 'LPSOMESTRUCT' to 'int'
What am I missing here? How to avoid this warning?
Thanks.
%x expects an unsigned. What you're printing is a pointer. To do that correctly, you normally want to use %p. To be pedantically correct, that expects a pointer to void, so you'll need to cast it:
printf("%p\n", (void *)val);
In reality, most current implementations use the same format for all pointers, in which case the cast will be vacuous. Of course, given the C++ tag, most of the code you've included becomes questionable at best (other than the parts like LPSOMESTRUCT, which are questionable regardless). In C++, you normally want something more like:
struct somestruct {
int a;
int b;
};
somestruct *val = new somestruct; // even this is questionable.
std::cout << val;
Use the %p format specifier to print a pointer.
printf("%p\n", val);
If you want to cast then using reinterpret_cast instead of static_cast might do the trick here.
With printf try using the %zu instead of %x for printing out a pointer because the pointer is of unsigned integer type (ie %zu).
printf("%zu \n", val);
Just one other thing, being a c++ program is there a reason why you are using malloc instead of new?
As this is tagged C++, can I just point out that you do not need typedefs when creating structs in that language:
typedef struct _somestruct {
int a;
int b;
}SOMESTRUCT,*LPSOMESTRUCT;
should be:
struct SOMESTRUCT {
int a;
int b;
};
Also, it is considered by many to be bad practice to create typedefs like LPSOMESTRUCT which hide the fact that a type is a pointer.