I want to browse a part of the RAM. I tried with this code:
#include <stdio.h>
#include <string.h>
#define MIN ((volatile unsigned char*)0x00000000)
#define MAX ((volatile unsigned char*)0x0000ffff)
main()
{
volatile char* c;
for (c=MIN; c<MAX;c++) printf("c[%p]= %c\n",c,*c);
}
However the compiler display this message:
warning: comparison of distinct pointer types lacks a cast.
How I can resolve this problem?
c should have the same type as MIM/MAX: volatile unsigned char* c;.
Related
I wrote a small piece of code to understand how the offsetof macro works in the background. Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
/* Getting the offset of a variable inside a struct */
typedef struct {
int a;
char b[23];
float c;
} MyStructType;
unsigned offset = (unsigned)(&((MyStructType * )NULL)->c);
printf("offset = %u\n", offset);
return 0;
}
However, if I run it I get a warning message:
WARNING: cast from pointer to integer of different size [-Wpointer-to-int-cast]
However, if I look at the original offsetof macro in c, the code looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
int main(void)
{
/* Getting the offset of a variable inside a struct */
typedef struct {
int a;
char b[23];
float c;
} MyStructType;
unsigned offset = offsetof(MyStructType, c);
printf("offset = %u\n", offset);
return 0;
}
So why do I get the warning as I cast to unsigned ? It appears to be the type for the offsetof macro. This is puzzling me.
As mch commented, unsigned is not the right type; it's 32-bit on pretty much all real-world systems. The offsetof macro is supposed to produce a result of type size_t, which is what you "should" be casting to here. I think you're confused by the code you found storing the result into an object of type unsigned; that's okay as long as they're sure the value is small, but it doesn't mean the type of the expression offsetof(MyStructType, c); was unsigned. C allows you to silently assign a larger integer type into a smaller one.
However, no matter what you do, this is not a valid implementation of offsetof and has undefined behavior (via applying -> to an invalid pointer). The way you get a working offsetof without UB is #include <stddef.h>.
While I'm trying to explore possibilities of arrays in C in ANSI, I'm confronted with an issue. Here's my code:
#include <stdio.h>
#include <string.h>
static int MAXLIGNE = 5000;
char *ptrlig[MAXLIGNE]; // PTR SUR LA LIGNE DE TXT // GOT AN ISSUE :
// VARIABLY MODIFIED PTRLIG # FILESCOPE
int lirelignes(char *ptrlig[], int nlignes);
void ecrirelignes(char *ptrlig[], int nlignes);
void trirapide(char *ptrlig[], int gauche, int droite);
Error from the GCC :
VARIABLY MODIFIED PTRLIG at FILESCOPE
I've seen that 'const' type may create that kind of issues. I tried to make it like :
#include <stdio.h>
#include <string.h>
static int MAXLIGNE = 5000;
unsigned char *ptrlig[MAXLIGNE];
But that doesn't seem to change anything in this case.
The length of an array defined at file scope must be a compile time constant, and the value of another variable does not qualify as such.
If you want to use a name for the length of this array, you'll need to use a macro:
#define MAXLIGNE 5000
char *ptrlig[MAXLIGNE];
The macro does a direct text substitution, so after the preprocessor stage it is the same as char *ptrlig[5000];
I'm not sure how to create a Struct in C with its variables having different bit sizes, for example:
I want to create a struct with one variable as an 8-bit integer, one variable as an 16-bit boolean, one as an 8-bit boolean, one as a 32-bit floating point number etc.
I'm coming from java so all this is very confusing, thanks.
#include <stdio.h>
#include<stdbool.h>
struct{
float d; // By default 32 bits are initialized
unsigned int a: 8;
bool my_bool_8;
bool my_bool_16;
}nibble;
int main()
{
printf("Size of structure is %lu\n", sizeof(nibble));
printf("Size of my_bool_8 is %zu\n", sizeof(nibble.my_bool_8));
return 0;
}
It depends from compiler and platform. For 8-bit integer, perhaps, you can use "int8_t" type. For 32-bit floating point - "float", but you must read documentation for your compiler.
Maybe this small example response your question:
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
struct {
uint8_t my_int_8;
int16_t my_bool_16;
bool my_bool_8;
float my_float;
} test;
int main(const int argc, const char* argv[]) {
printf("sizeof(my_int_8)=%zu\n", sizeof(test.my_int_8));
printf("sizeof(my_bool_16)=%zu\n", sizeof(test.my_bool_16));
printf("sizeof(my_bool_8)=%zu\n", sizeof(test.my_bool_8));
printf("sizeof(my_float)=%zu\n", sizeof(test.my_float));
}
I'm trying to initialize a global-scoped const variable with a value that is byte-swapped appropriately.
#include <stdio.h>
#include <stdint.h>
#include <arpa/inet.h>
const uint32_t a = ntohl(0x11223344);
int main(int argc, char const *argv[])
{
printf("%08x\n", a);
return 0;
}
Using gcc this fails with "error: initializer element is not constant". Yeah, okay, so the gcc header has ntohl() defined as a function or as "do {...} while (0)" or something similar that can't be evaluated at compile time. Bummer.
Is there anything I can do which will achieve the same end? I need to initialize the value for the appropriate endedness, and I want it to be a globally-scoped const. Is there any way to convince gcc to do this, short of rolling my own ntohl-like macro?
(BTW, I note that clang has ntohl() defined such that it can be evaluated at compile time. The above code sample works perfectly with clang. Unfortunately I don't get my pick of compilers.)
Section 6.7.8/4 of the standard reads
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
A call to ntohl is neither a constant expression nor a string literal. You can’t get there from here.
But global variables are bad anyway, and I suspect this may be a premature optimization. The easy fix is to use the expression directly in your code, which will have no effect at all on big-endian platforms, e.g.,
void foo(void)
{
const unit32_t a = ntohl(0x11223344);
/* ... */
}
Even better, use a preprocessor macro, as in
#define POTRZEBIE ntohl(0x11223344)
void bar(void)
{
const unit32_t a = POTRZEBIE;
/* ... */
}
On variables with automatic storage, the const qualifier means single assignment, so there is no problem with the above usage.
Initialize it in main() or use something like (assuming Linux):
#include <endian.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
const uint32_t a = 0x44332211;
#else
const uint32_t a = 0x11223344;
#endif
or perhaps
#include <endian.h>
#define A_ADDR 0x11223344
#if __BYTE_ORDER == __LITTLE_ENDIAN
const uint32_t a = __bswap_constant_32(A_ADDR);
#else
const uint32_t a = A_ADDR;
#endif
When I compile the following code:
#define _POSIX_C_SOURCE 200112L
#define _ISOC99_SOURCE
#define __EXTENSIONS__
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
char *symlinkpath = argv[1];
char actualpath [PATH_MAX];
char *ptr;
ptr = realpath(symlinkpath, actualpath);
printf("%s\n", ptr);
}
I get a warning on the line that contains the call to the realpath function, saying:
warning: assignment makes pointer from integer without a cast
Anybody know what's up? I'm running Ubuntu Linux 9.04
This is very simple. Glibc treats realpath() as a GNU extension, not POSIX. So, add this line:
#define _GNU_SOURCE
... prior to including stdlib.h so that it is prototyped and known to to return char *. Otherwise, gcc is going to assume it returns the default type of int. The prototype in stdlib.h is not seen unless _GNU_SOURCE is defined.
The following complies fine without warnings with -Wall passed:
#include <stdio.h>
#include <limits.h>
#define _GNU_SOURCE
#include <stdlib.h>
int
main(int argc, char *argv[])
{
char *symlinkpath = argv[1];
char actualpath [PATH_MAX];
char *ptr;
ptr = realpath(symlinkpath, actualpath);
printf("%s\n", ptr);
return 0;
}
You will see similar behavior with other popular extensions such as asprintf(). Its worth a look at /usr/include/ to see exactly how much that macro turns on and what it changes.
The compiler doesn't know what realpath is, so it assumes it's a function returning int. It does this for historical reasons: a lot of older C programs relied on it doing this.
You're probably missing the declaration of it, e.g. by forgetting to #include its header file.