Printf Type Qualifier Mismatch In Assignment

  • What's the best way to get forum help with a code problem?

    Create a minimal, self-contained example that demonstrates the problem. It should be a single C file -- no header files unless the problem specifically involves header files, and no external dependencies so that anyone can compile it. Remove any code (including commented-out code) that is not related to the problem. Use standard C types like char and int, not typedefs like DWORD or UINT8. Include your configuration fuse settings in the code. If the code compiles and runs, test the code in the simulator to confirm that it exhibits the problem. Attach the C file to your forum post.

    Do:

    • Tell us which PIC you're using.
    • Tell us which compiler you're using.
    • Tell us which version of the compiler you're using.
    • Tell us about any non-standard build options you're using (large memory model, large stack model, modified linker file, etc.)
    • Tell us if it's a or version of the compiler.
    • If it's a Hi-Tech/XC8 compiler, tell us if you're using PRO or STD mode.
    • Cut and paste any error messages into your post.

    Don't:

    • Type code into the forum.
    • Cut and paste code into the forum.
    • Put the code into your message with code tags.
    • Show an of the problem.
  • How can I remap a group of pins on different ports into a single structure?

    If you have pins scattered on different ports or pins that are not in the desired order on one port, and you're hoping to define something that lets you do , you can't. C places all of the members of a structure in address order. C does not support the concept of writing to scattered memory addresses in a single operation.

    There is no simple or clean mechanism to logically rearrange port pins. The most straightforward technique is to write a function that encapsulates the necessary operations on the port pins. See the following three questions for further discussion.

  • How can I make an array of port pins?
  • How can I declare a pointer to a port pin?

    You can't. The C language does not permit taking the address of a bit or of a bit-field member of a structure. This means you can't have pointers to bits or arrays of bits, whether or not they're port pins.

  • How can I pass a port pin as an argument to a function?

    You can't, because you can't take the address of a port pin (refer to the previous question). You can pass the value of a port pin to a function just like any other integer, but the function won't be able to modify the port pin.

    You can pass a reference to a port pin as an argument to a function, or make an array of port pin references, by using the address of the port (not the pin) and an identifier for the pin. For example:

    void set_port_pin(volatile unsigned char *port, unsigned char pin) { *port |= 1U << pin; } set_port_pin(&LATA, 7); This will set RA7 to 1. Refer to your compiler's header file for the correct type to use for port.

    Note that this type of code is grossly inefficient on a PIC, and will use far more code space and execution time than simply setting the pin value directly or through a macro, which is the preferred solution.

    If you need a further layer of abstraction that lets you refer to the ports themselves indirectly (e.g., a PC program that sends commands controlling the state of arbitrary port bits), place the port addresses in an array:

    volatile unsigned char * const lats[] = { &LATA, &LATB, &LATC }; /* an enum that defines indices into the ports array */ enum { MY_LATA = 0, MY_LATB = 1, MY_LATC = 2 }; void set_port_pin(unsigned char port, unsigned char pin) { *ports[port] |= 1U << pin; } set_port_pin(MY_LATB, 5);
  • Why am I getting a syntax error when I use a #define?

    You probably have a semicolon at the end of your #define.

    #define is not a statement, and does not end in a semicolon. A #define just does simple text substution; if you have a semicolon in your #define text, the preprocessor will insert that semicolon into your C code, possibly in a place where a semicolon is a syntax error.

  • What do these MPLAB C18 warnings mean?

    When compiling code that assigns pointers or passes them as function arguments, C18 tends to provide spurious warnings on valid code, or worse, fails to provide warnings on invalid code. These are the most commonly encountered issues with C18 pointer warnings:

    • type qualifier mismatch in assignment

      This means that an assignment (or passing an argument to a function) attempted to add, remove, or modify a qualifier. In C18, the qualifiers are const, volatile, rom, ram, near, and far.

      The most common source of this warning is mismatching a near and far qualifier on a call to a C library function. For example, a call to printf() will usually elicit this warning. If you are compiling with the default (small) memory model, the format string argument to printf() is qualified as "near rom", while the printf() function was actually compiled with the large memory model which uses "far rom" pointers, resulting in the qualifier mismatch.

      In this particular case, the warning is spurious, because the compiler simply converts the 16-bit near pointer to a 24-bit far pointer, and everything works as expected. The warning can be suppressed by adding a (const far rom char *) cast to the format string, or by compiling with the large memory model, or by recompiling the C library with the small memory model.

      In other cases, this warning probably indicates an error in your code, though bugs in the compiler cause it to elicit this warning on certain valid code sequences, such as:

      const void *cvp; int *ip; cvp = ip;
    • suspicious pointer conversion

      This is generally caused by a sign mismatch in a pointer assignment or function call. A common cause is using unsigned char for strings (strings are char, not unsigned char). For example:

      void func(char *string); unsigned char data[10]; func(data); Another common cause is passing a pointer to an incompatible type, such as passing a pointer to a two-dimensional array to a plain pointer: rom unsigned char array[2][3]; void func(rom unsigned char *ptr); func(array); or passing an integer to a function expecting a pointer: int foo; void func(int *ptr); func(foo); This warning can also be elicited by valid code, such as: void *vp; unsigned char *ccp; memcpy(vp, ccp, 0); To work around this bug, simply cast ccp to the type that memcpy() expects: memcpy(vp, (const void *)ccp, 0); A cleaner, safer solution is to wrap function calls that trigger spurious warning in macros: #define memcpy(a,b,c) memcpy((a),(const void*)(b),(c)) #define memcmp(a,b,c) memcmp((const void*)(a),(const void*)(b),(c)) #define strcpy(a,b) strcpy((char*)(a),(const char*)(b)) Of course these casts, like any casts, can mask errors in your program. But C18 gives you the unfortunate choice between casting and having warnings for valid code.
    • type mismatch in assignment

      This generally means an error in your code, such as:

      char *a; int *b; a = b; b = 0x1234; It can also be elicited by valid code such as: const void *cvp; int *ip; cvp = ip;
  • Why am I getting a syntax error on a declaration in this simple code? void main(void) { int a; a = 42; int b; b = a; } Because most PIC C compilers support the C90 standard, which does not permit mixing statements and declarations. This feature was added to the C99 standard. C90 requires that all declarations appear at the beginning of a block.
  • How can I save a float, int, double, long, array, or structure to EEPROM? void eeprom_write_block(void *ptr, unsigned short addr, unsigned char len) { unsigned char *data = ptr; while (len--) eeprom_write_byte(addr++, *data++); } /* examples of usage: */ struct { int a; unsigned char b; } s; unsigned int c; float d; unsigned char array[10]; eeprom_write_block(&s, 10, sizeof s); eeprom_write_block(&c, 20, sizeof c); eeprom_write_block(&d, 30, sizeof d); eeprom_write_block(array, 40, sizeof array);

    Note that this code takes advantage of C's void type to eliminate casting or the need for different functions for saving different types.

    A similar method is used to read:

    void eeprom_read_block(void *ptr, unsigned short addr, unsigned char len) { unsigned char *data = ptr; while (len--) *data++ = eeprom_read_byte(addr++); } These routines assume you have a routine that can read and write byte to your EEPROM.
  • How can I share a global struct or other type among different C files?

    In globals.h:

    /* declare an int */ extern int global_int; /* declare a struct type */ struct tag { int a; int b; }; /* declare a struct */ extern struct tag global_struct; /* declare a string that's initialized elsewhere */ extern const char string[]; In globals.c: #include /* define the int */ int global_int; /* define the struct */ struct tag global_struct; /* define the string */ const char string[] = "Hello, world."; In main.c: #include #include <stdio.h> void main(void) { /* use the globals */ global_struct.b = 42; global_int = 0x4242; printf("%s\n", string); }
  • How can I find what's causing the behavior in my MPLAB C18 program?

    Some common causes of behavior:

    • An error in your interrupt declaration

      C18's interrupt declaration scheme is extremely error prone, and none of the errors described below will result in a compiler diagnostic. Interrupt declaration errors are one of the most common causes of behavior. Erroneous interrupt declarations can appear to work correctly, but then subsequently fail when modifying other parts of the code, upgrading the compiler, or moving to a different processor.

      Ensure you haven't mixed up #pragma code addresses, or interrupt vs. interruptlow keywords, or defined a low-priority interrupt with #pragma interrupt, or enabled low-priority interrupts with only a high-priority handler, or vice versa, or omitted the necessary #pragma code and #pragma interrupt statements, or configured a specific interrupt at one priority with the code that handles it defined at the other priority. If you're using assembly language springboard functions, ensure these are actually present in your code.

    • Spending too much time in the ISR

      Don't use delays, write to slow peripherals like LCDs, write to EEPROM, or perform other time-consuming tasks in the ISR. If you have an interrupt that occurs more quickly than one of these tasks, your application never gets out of the ISR and your main code never runs.

    • Calling functions from the ISR
    • Manipulating GIE and/or GIEL in the interrupt handler. These are enabled and disabled automatically by the PIC; enabling them in the ISR can cause unexpected reentrancy.
    • Software stack overflow
    • Inappropriate modifications to the linker file

      If you've modified the linker file to create an object larger than 256 bytes, make sure you've followed all of the instructions here, especially the part about accessing the object through a pointer.

    • Writing past the end of an array
    • Writing through an uninitialized pointer
    • Not using the variant of the startup code when standard C zeroing behavior is expected.
    • Not compiling with the large memory model on a 128K PIC
    • Using a PIC with the fast interrupt errata

      The easiest workaround for this errata is to use the interruptlow keyword on the high-priority interrupt.

    • Compiling for extended mode with the PIC configured in standard mode, or vice versa.
  • How can I debug a software stack overflow in MPLAB C18?

    Start by reading about how the software stack is implemented in the chapter of the user's guide.

    Generally, PICs with at least 512 bytes of RAM have a 256 byte stack by default, and PICs with less RAM have a 64 byte stack by default. Check your PIC's generic linker file in bin/LKR to see how large the stack is and where it's located.

    Look for large objects that use stack space. Things that are allocated on the stack include function arguments and local variables in functions which do not have the or qualifiers. Identify large structures and arrays and move them off of the stack by making them or global, or pass a pointer to the object rather than passing the entire object. Some library functions, such as the printf() family, can use more than 64 bytes of stack space, which alone can blow the stack on parts with 64 bytes of stack space.

    If you're still getting a stack overflow, here are some techniques to find it:

    • Set a breakpoint at the beginning of your program. When you hit the breakpoint, fill the stack with a known value, such as 0xAA. This can be done in MPLAB IDE by opening the File Registers window, right clicking, and selecting Fill Registers. Let your program continue running until it starts misbehaving. Stop your program and inspect the stack area in the File Registers window; if all of your known values have been overwritten, you know you have a stack overflow.
    • Set a complex breakpoint on the last memory address of the stack. This will cause the debugger to halt at the point of the stack overflow. To set a complex breakpoint in the MPLAB IDE Simulator, select Debugger... Complex Breakpoints... Add Breakpoint... Data Memory. Enter the last address of the stack memory (for example, if your 256 byte stack is at 0x100, enter 0x1FF), and ensure the breakpoint type is . Other debuggers might have slightly different methods for creating a complex breakpoint (or may not support complex breakpoints).
    • Since FSR1 is the stack pointer, you can inspect it at various points in your program to see how much stack has been used.
  • What is the best way to declare a C18 interrupt service routine (ISR)? #pragma code isr=0x08 #pragma interrupt isr void isr(void) { /* interrupt handling code here */ } #pragma code This avoids the assembly language springboard function which
    • wastes code space
    • increases interrupt latency
    • is ugly.

    This technique can generally only be used when not using interrupt priorities, which are generally not needed.

    If you need interrupt priorities, this is how to declare the two interrupt handlers:

    #pragma interrupt high_isr void high_isr(void) { /* high priority interrupt handling code here */ } #pragma interruptlow low_isr void low_isr(void) { /* low priority interrupt handling code here */ } #pragma code high_vector=0x08 void high_vector(void) { _asm GOTO high_isr _endasm } #pragma code low_vector=0x18 void low_vector(void) { _asm GOTO low_isr _endasm } #pragma code Yes, you really need five pragmas and four functions to declare two ISRs in C18. And because the vectors have to be defined as functions, there will be a wasted RETURN instruction in each of them -- C18 isn't smart enough to optimize the RETURNs out.
  • Should I use interrupt priorities on the PIC18?

    Probably not. By default (IPEN = 0), the PIC18's interrupts operate in PIC16 compatibility mode. This means there is a single interrupt vector at address 0x08, and no interrupts will vector to address 0x18. Even in compatibility mode, interrupts take advantage of the fast register stack, which makes zero-cycle context save/restore possible, so there is no inherent disadvantage to using compatibility mode. The disadvantages to using interrupt priorities are many:

    • More interrupt setup code
    • More complex ISR declaration
    • Higher latency for high-priority interrupts due to the necessary springboard GOTO
    • Much higher latency for low-priority interrupts since they can't use the fast register stack
    • Increased code space usage due to all of the above.
    • More hardware and software stack space is required.

    Even ignoring the disadvantages of interrupt priorities, few applications actually need them to perform correctly. A well-written interrupt handler can process all of its interrupts quickly enough to prevent any interrupts from being lost.

    A typical example of a situation that needs interrupt priorities is high-speed clock coming in on an INT pin that has very tight timing requirements. In such a case, it makes sense to enable interrupt priorities, and configure the INT interrupt as the only high-priority interrupt. Using multiple high-priority interrupts is not much different than using compatibility mode, and thus is generally pointless.

  • Why is my C18 interrupt behaving strangely or not running as fast as I expect?

    The most common cause is calling a function from the interrupt handler. In C18, calling a function from the interrupt handler triggers a worst-case context save. This results in interrupt latency of 50 instruction cycles or more, and total interrupt context save/restore overhead of 100 cycles or more. This makes high-speed interrupts impossible.

    Note that the worst-case context save occurs even if the called function has no parameters or local variables, or even if the function is never actually called. The mere presence of a function call statement in the ISR triggers the worst-case scenario on every interrupt.

    The easiest solution to this is simply not to call any functions from the interrupt handler, which will give best-case context saving. There is a more involved solution available if you absolutely must call functions from the ISR (local mirror).

    Other possible causes are listed here.

  • When should I use volatile?

    The volatile qualifier originates with the rule in C:

    In the abstract machine, all expressions are evaluated as specified by the semantics. An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced (including any caused by calling a function or accessing a volatile object).
    The critical part here is, . For example, int i; PORTA = 1; for (i = 0; i < 10; i++) ; PORTA = 2; Your expectation might be that 1 would be written to PORTA, then a delay, then 2 would be written to PORTA. But the compiler is free to just do , or even to generate no code at all. This is because a compiler can look at the code and realize there are from assigning 1 to PORTA or from the loop.

    But PORTA works as expected because it is declared as volatile in the compiler's header files; every operation on PORTA must be carried out exactly as stated by the programmer:

    An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine
    tells the compiler to do exactly what the programmer said to do. To correct the code fragment above, must also be volatile to ensure the delay loop is executed exactly as stated.

    volatile is also relevant in interrupt handlers in cases like this:

    int interrupt_flag; int main(void) { interrupt_flag = 0; while (interrupt_flag == 0) /* wait for interrupt */ ; /* do stuff */ } The compiler can look at that code and realize that interrupt_flag is 0, and will always remain 0, so there is no need for it to generate any code at all for main(), even though you might have an interrupt handler somewhere that sets interrupt_flag to 1. The solution is to make interrupt_flag volatile, so that the compiler understands that it

    Note that volatile does not provide atomic access. In the previous example, it will take multiple CPU instructions to compare interrupt_flag against 0 on an eight-bit processor. The volatile keyword does not prevent an interrupt from occurring in the middle of this sequence of instructions, which means interrupt_flag may take on an unexpected value with a properly timed interrupt. Atomic access requires additional protection, such as disabling interrupts around the comparison.

  • Should I just make everything volatile to be safe?

    No. With a modern C compiler, you have to forget about the idea that the compiler is going to blindly follow your instructions step by step. You have to think in terms of what side effects your program generates.

    In an embedded program, side effects are almost exclusively caused by reading or writing the processor's special function registers. If you're blinking an LED, sending data over a UART, or writing to internal EEPROM, you are accessing a special register that is declared as volatile, so all of these things are guaranteed to happen. But other concepts, like assigning a value to a variable, or the passage of time caused by a delay loop, are not side effects. For example:

    int main(void) { int a, b; a = 1; a *= 2; b = 3; PORTA = a + b; } The only side effect in this program is writing 5 to PORTA. Since PORTA is volatile, we are guaranteed that will happen. What we aren't guaranteed is that some memory location called will have the value 1 written to it, or that the processor's multiply instruction will be used in calculating the value to be written to PORTA. If the compiler is smart enough to replace the above with int main(void) { PORTA = 5; } we've achieved the same result with less code space and faster execution time.

    There is one situation where you'd want to declare and volatile in the above code: when you're debugging. If your compiler is smart enough to optimize all of the assignments away, you won't be able to step through the assignments in the debugger to make sure they're working the way you want. Using the volatile keyword temporarily during debugging can work around this, as can choosing a lower optimization level during debugging.

  • I just upgraded C18 and there's no linker script for my processor?

    Recent versions of C18 (after 3.20 or so) include a slightly more powerful linker which does not require including a linker script in your project. The linker now has a single per processor type, which can be used to build a standard, extended mode, or ICD debug build; the IDE passes options to the linker describing the build type and processor type, and the linker chooses the appropriate script automatically.

    If you have a non-standard requirement like a bootloader, you can still include a linker script in your project. The generic linker scripts are located in the bin/LKR subdirectory of the compiler.

  • How can I pass a pointer to a two-dimensional array to a function, or declare a pointer to a two-dimensional array?

    With a two-dimensional array, the compiler needs to know how many elements are in a column to move from one row to the next, but movement within a row is always by a single element, so the compiler doesn't need to know the number of rows. Thus the pointer declaration must include the number of columns in the array:

    char array[2][3] = { "19", "42" }; void func(char (*p)[3]) { puts(p[1]); // prints "42" } func(array); /* or */ char (*p)[3]; p = array;
  • What is Fosc? How is Fosc related to the clock speed? Does the PLL change Fosc?

    Fosc is a term that's not used consistently throughout the data sheet.

    When you're looking at the electrical specifications, Fosc means the actual frequency of the external (or internal) clock.

    When you're looking at the configuration bits, Fosc means the type of the oscillator (e.g., XT, HS), which isn't related to the clock speed at all.

    When you're looking at something that affects software, such as the equations for setting up the PWM or UART or I2C baud rate, Fosc means the CPU clock speed, which might or might not be the same as the oscillator speed. The CPU clock speed is the oscillator speed scaled up or down by the chain of oscillator dividers and multipliers. For example, if you're using a PIC with a 4 MHz external oscillator and no PLL, Fosc is 4 MHz. If you're using a PIC with an 8 MHz internal oscillator and a 4x PLL, Fosc is 32 MHz. Fcy is the instruction clock, which is Fosc / 4 on an 8-bit PIC (each instruction takes four clock cycles).

  • Why does the UART suddenly stop receiving data? Transmit still works.

    You are getting overrun errors. An overrun error occurs when the UART's receive FIFO is full, and another byte of data arrives. When this happens, the UART turns off its receiver, and sets the OERR bit. The OERR bit is read-only and cannot be cleared in software. To restart the UART and clear OERR, it is necessary to clear and then set CREN.

    Overrun errors are caused by software bugs. Unlike framing errors, they are not caused by noise, baud rate mismatches, or other external events. Contrary to popular belief, you do not need to check for overrun errors in your software. Overrun errors are not possible in correctly-written software.

    To avoid overruns, receive serial data in an interrupt, not in a busy loop, and ensure your interrupt handler has low latency.

  • Why is my port pin not behaving the way I expect?

    Most likely because you haven't disabled the analog features on the port. When a pin is attached to the A/D converter, it will default to analog mode. Such pins are generally labeled as ANxx. Pins on PORTA are almost always analog, while pins on other ports might also be analog. Some 18F PICs, such as the 18F4550 family, have analog pins on PORTB, but these pins can sometimes be made to default to digital with one of the configuration words.

    Some PICs also have comparators that default to enabled and need to be disabled to allow use of their pins in digital mode.

    When a pin is in analog mode, a digital read from the port will always return 0. The pin will still work as a digital output, but because the pin reads 0, it will be particularly susceptible to read-modify-write effects.

    Consult the A/D converter chapter of your data sheet on how to disable analog features. There is no single method; Microchip has used a wide variety of techniques in different PIC families. Note that simply turning off the A/D converter is not enough; each analog pin must be configured for digital use.

    If you have disabled analog features and are still not seeing the expected behavior, it might be the read-modify-write effect.

  • Can I sleep in an ISR?

    When an interrupt occurs on a PIC, two things happen:

    1. The program counter is pushed on the stack
    2. The PIC branches to the interrupt vector address.

    That's it. The PIC does not store any internal state indicating that it's ; it continues executing code exactly the same way as it did before it entered the ISR. The ISR is purely a software concept that the PIC knows nothing about. This means you can execute a SLEEP instruction or do anything else in an ISR that you could do in your non-ISR code. Whether sleeping in the ISR is a good idea or not depends on the application.

  • With C18, how can I place some data at a specific address in ROM without using a linker script?

    Use #pragma romdata. For example:

    #pragma romdata mac_addr=0x800 rom unsigned char mac_addr[] = { 1, 2, 3, 4, 5, 6 }; #pragma romdata
  • Why am I getting a syntax error at the end of my header file?

    Because the file doesn't end in a newline.

  • What do the different MPLAB C18 memory models do?

    They do not make more RAM or ROM available. They will not fix a error, or any other compiler or linker error.

    The default model is the small model (MPLAB IDE refers to this as the ). This should be used on any PIC with 64KB or less of program memory.

    The large model should be enabled when using a PIC with more than 64KB of program memory. The only effect the large model has is to make pointers to rom 24 bits instead of 16 bits. If you don't use the large model on a PIC with more than 64KB, the code will compile and link successfully, but if you have pointers to any objects at addresses above 64K, accesses to those objects will fail, since a 16-bit pointer can't point at an address above 64K.

    The large model increases the amount of code space used since the larger pointers have more overhead.

    MPLAB IDE also incorrectly refers to a option. C18 does not have a data model; this option refers to an optimization that places all data in the access bank (). By default, C18 uses all available banked RAM (). While certain unusual applications that use very little RAM could benefit from this optimization, it should normally be at the default (off) setting.

  • What is read-modify-write (RMW)?

    Consider the following code:

    RB0 = 1; RB1 = 1; A reasonable compiler will generate a BSF (bit set file register) instruction for each of these C statements. The BSF instruction does not simply set the value of a single bit. Internally, the PIC reads all eight bits from the port, sets the desired bit, and writes all eight bits back out to the port. For a single BSF instruction by itself, this doesn't cause an issue. But when two BSFs on the same port happen back-to-back, the first BSF may not work as expected.

    The problem occurs when the second BSF reads back the state of the port. If the voltage on RB0 has not yet risen to the level the PIC considers a logic 1 (Vih), the PIC will read back a 0 for RB0, set bit 1 for RB1, and write the result back out to the port. This leaves RB0 at 0, and RB1 at 1, which is not the desired result.

    RMW can become more of an issue with higher PIC clock frequencies, because the amount of time between instructions is smaller, requiring the port output to have a faster rise time to avoid being read back in the wrong state.

    There are several different fixes for the RMW issue; these are listed in order of best to worst:

    • On the PIC18, PIC24/dsPIC, and enhanced midrange parts (PIC16F1xxx, PIC12F1xxx, PIC10F3xx), port latch registers are available. Reading from a latch register does not read back the state of the port pins, so BSF instructions can safely be used back-to-back. On these PICs, all writes should be done to these LAT registers, and all reads from the PORT registers. Never write to the PORT registers.
    • If using a baseline or standard midrange part (PIC10/12/16 parts other than those listed above), first ensure that all analog features have been disabled on the pins in question. A digital read of an analog pin is always zero, so trying to set two analog pins high will always result in the first one being set back to zero. Note that disabling the A/D converter does not disable the analog features on the pins; look for registers like CMCON, ANSEL, ANSELA, etc.

      If the problem persists, use a shadow register for the port. For example:

      union { unsigned char byte; struct { unsigned RB0:1; unsigned RB1:1; unsigned RB2:1; unsigned RB3:1; unsigned RB4:1; unsigned RB5:1; unsigned RB6:1; unsigned RB7:1; } bits; } portb; portb.bits.RB0 = 1; portb.bits.RB1 = 1; PORTB = portb.byte; With the shadow register, the write to the actual port is a full eight bits (no BSF instructions are used), so there is no RMW issue.
    • Insert a delay between writing to each port pin. This gives the port pin time to reach Vih so that its state will be read back correctly on the next BSF. The problem with this approach is that it's not trivial to determine how much of a delay is necessary, and changes made down the road to the PIC's clock speed or board layout can cause RMW issues to unexpectedly reappear.

    Section 9.10.2 of the PICmicro Mid-Range MCU Family Reference Manual (local mirror) has additional discussion and timing diagrams that explain what happens in each clock cycle.

  • Why does the PIC's flash and/or EEPROM get erased, have all FFs, or contain corrupted values when powering the PIC on or off?

    Because the PIC is browning out: operating at a voltage below the allowed minimum. The brownout itself does not cause flash or EEPROM corruption, but when the PIC is in brownout, it is operating in an undefined state. This means that the program counter can take on a random value which will cause random code to be executed. Murphy's Law says that the most likely place for this random code execution to occur is in your flash or EEPROM write routine.

    The fix is to prevent the PIC from browning out. This can be done with an external supervisor chip such as the MCP100, or by enabling the PIC's brownout reset feature. If you use the PIC's brownout reset, ensure that you select a reset voltage that is within the PIC's rated operating range. Some PICs, especially those that come in low-voltage variants, have a wide range of BOR voltage options, some of which will not actually protect against brownout.

    Brownout cannot be worked around in software.

  • How does the PORTB change interrupt work?
  • How can I tell which pin caused the PORTB interrupt?
  • How can I clear the RBIF flag?

    When the PORTB change interrupt is enabled, the PIC continuously compares the value on each of the PORTB change pins with the the last PORTB values read by your software. When the current pin value of any pin doesn't match the last read value, RBIF is set.

    On many PICs, the PIC does not keep track of which pin change set RBIF (enhanced midrange parts are the exception); this has to be determined in software. One common method is to XOR the current PORTB value with the previous value:

    if (RBIF) { unsigned char changes, portb; static unsigned char last_portb; portb = PORTB; RBIF = 0; changes = portb ^ last_portb; last_portb = portb; /* process the bits in "changes" */ } This code leaves a bit set in changes for each pin that changed state.

    Note that the RBIF flag is cleared after reading the value of PORTB. Reading PORTB updates the PIC's change-detection latch with the current value of PORTB so that it no longer sees a mismatch between the current pin state and the last-read state. As long as this mismatch condition is present, RBIF cannot be cleared.

    The PORTB change interrupt has a major design error in may PICs and is not recommend for use as a general-purpose interrupt. It should only be used as a wake-from-sleep source.

  • What does mean?

    C18 does not permit using function pointers while compiling in the mode. If you want to use function pointers, don't compile in overlay mode (-sco) or don't use the overlay keyword. The in the error message is meaningless; they will not ever be supported, since C18 development has been halted.

  • Where can I find the settings for the MPLAB C18 directive?

    In MPLAB 8 IDE, look under Help...Topics...PIC18 Config Settings. In MPLAB X IDE, look under Help...Help Contents...C18 Toolchain...C18 Configuration Settings.

    Another option is to run the compiler from the command line:

    mcc18 --help-config -p=18f87k22 | more Note the the configuration settings are built in to the compiler and are not in the processor's header file.
  • Why am I getting a syntax error on my directive?

    Because you have a #define FOSC ..." directive somewhere in your code.

  • How can I fix an error when using printf() with a Hi-Tech/XC8 compiler?

    Hi-Tech's printf() does not send its output to any particular device by default. It calls putch() for that purpose, and you must provide an implementation of putch() that sends the output where you want. This can be a UART, LCD, etc. A simple implementation that sends the output to the UART is:

    void putch(char c) { while (!TXIF) ; TXREG = c; } printf() does not initialize the UART or any other hardware; you must do that yourself.
  • Why does a simple function return an incorrect value in MPLAB C18?

    Because there is no function prototype in scope at the point the function is called. This means C18 assumes the return value of the function is int (this is standard C behavior), and if the return value isn't actually int, you'll get garbage as the return value.

    C18 has an calling convention; rather than passing all return values on the stack, it uses different registers depending on the type of the return value. So the garbage value that's returned probably won't even be related the correct return value at all.

  • How can I combine two bytes into an integer?

    There are several different ways to do this. The best way is to use shifting:

    unsigned int i unsigned char a, b; a = 42; b = 24; i = (a << 8) | b; This creates an int with as the most significant byte (MSB) and as the least significant byte (LSB). This has two major advantages over other approaches:
    • You can easily tell which byte is the MSB by looking at the code.
    • This code does the same thing on any standard C compiler or any processor.

    On the surface, this code might appear to be inefficient since it involves shifting the MSB eight bits -- an especially bad idea on a PIC. But because of C's as-if rule, this code does not have to be interpreted literally by the compiler. Any reasonable compiler will recognize this common idiom and simply assign to the upper byte of .

    If you're using MPLAB C18 in its default non-standard mode (integer promotions disabled), the above code won't work, because C18 doesn't convert to an int as standard C requires. You can either enable integer promotions, or add a cast:

    i = ((unsigned int)a << 8) | b;

    There are two additional approaches:

    • Use a union: union { struct { unsigned char a, b; } byte; unsigned int i; } u; u.byte.a = 42; u.byte.b = 24; // u.i now contains a and b assembled into an int This approach has several problems:
      • It isn't obvious which byte is the MSB and which is the LSB. You can call one byte and the other , but you have to read the compiler's implementation details to know which is which.
      • On different compilers and processors, which byte is the MSB will vary. The code will compile, but will give incorrect results.
      • Writing into one member of a union and reading from a different member is in C. This means that you have to read the compiler's implementation documentation to determine whether this approach will even work.
    • Use a pointer: unsigned char buff[2]; unsigned int i; buff[0] = 42; buff[1] = 24; i = *(unsigned int*)buff; As well as being the least readable, this approach suffers from some of the same problems as the union approach:
      • It isn't obvious which byte in is the MSB and which is the LSB.
      • On different compilers and processors, which byte is the MSB will vary.
  • How can I split an integer into two bytes? unsigned int i unsigned char a, b; i = 4242; a = (i >> 8) & 0xFF; b = i & 0xFF; Just like the code to combine bytes into an integer, this code does exactly the same thing on any compiler and processor, and it's obvious which byte is the LSB (b) and which is the MSB (a). The union and pointer approaches described in that link can also be used for this task, but they suffer from the same disadvantages.
  • Why am I getting even though I have a prototype?

    Because you really don't have a prototype. You might have something like

    void func(); which is not a function prototype. C requires that a function prototype specify the number and types of the function's parameters. If there are no parameters, void must be explicitly specified: void func(void);
  • What does mean?

    Hi-Tech's STD compilers for the PIC18 sometimes require a certain amount of manual memory management (this is not true with the PRO compilers or XC8 compilers). Here is some background and a workaround for the error:

    Given these qualifiers:

    1. uninitialized
    2. static storage duration (at file scope and/or using the static keyword)
    3. type char (including arrays)
    4. size greater than 256 bytes

    If an object is ((1 and 2 and 3) or (1 and 2 and 4)), it is placed in the bigbss psect. Any remaining objects which are (1 and 2) are placed in a bss psect.

    Each C module has one bss psect of at most 256 bytes. Thus each module can have no more than a total of 256 bytes of bss objects; this restriction may require moving objects into separate modules. E.g., two int[65] arrays could not appear in one module, because their total size is 260 bytes, and they do not meet the requirements that would place them in the bigbss psect. But if each array is placed in a separate .c file, the program should build successfully.

    Another restriction is that a bss psect cannot straddle a bank boundary. Thus e.g. a PIC with 512 bytes of RAM could not have three int[65] arrays, even in separate modules. Even though their total size is only 390 bytes, there is no way to place them without straddling banks. Objects in bigbss can straddle banks, and do not have per-module size restrictions. But there is no way to force an object into bigbss.

    If your error relates to the data psect (initialized data) rather than a bss psect, the above workaround doesn't apply. The compiler has a hard limit of 256 bytes for the entire program's data psect. The workarounds for this issue are:

    • Replace initialized data with data that's assigned initial values at runtime.
    • Make initialized data const where possible.
    • Wrap initialized data in a super-struct; a single initialized object that's larger than 256 bytes will be placed in a bigdata psect.
  • What does mean?

    MPLAB C18 has a limitation on how much stack data can be accessed in a single frame (one function). This is about 120 bytes in standard mode and about 95 bytes in extended mode. This limitation cannot be overcome by increasing the stack size. One workaround is to make any large auto objects in the function static, which takes them off the stack.

  • Why is the Hi-Tech/XC8 compiler issuing warnings even though the variables are being used?

    This warning might be more clear if it stated that the variable's value is not used.

    As was noted in the discussion of the volatile keyword, the compiler is only looking for the side effects caused by your program. Side effects are limited to reads and writes to the processor's volatile special function registers. Any other code that doesn't cause side effects may be optimized away, resulting in unexpected warnings.

    For example, given this code:

    void main(void) { unsigned char a, b; a = 1; b = a; } PICC-18 9.80 will warn that is not used and that the assignment generates no code. Looking at the list file, no code is generated for main(). This is because the program has no side effects (it does not write to any volatile special function registers), so the compiler is permitted to optimize the entire program away. Even though is assigned to and appears to be in the code, its value is never used, so there is no reason to generate code for it.

    Now consider this code:

    void main(void) { unsigned char a, b; a = 1; b = a; PORTA = b; } This compiles with no warnings, because the value of is used to write to PORTA, which is a volatile object that causes side effects. However, if you look at the list file, you'll see that compiler still didn't blindly follow the code: 52 ;t.c: 71: PORTA = b; 53 001FF8 0E01 movlw 1 54 001FFA 6E80 movwf 3968,c ;volatile All of the references to and have been removed, and the compiler correctly generates code only for the necessary side effect: loading 1 into PORTA.
  • What does 'The Extended CPU Mode configuration bit is enabled, but the program was not built using extended CPU instructions.' mean?

    Newer PIC18s have a feature called the extended instruction set. When this feature is enabled, it adds some new instructions and changes the behavior of many existing instructions. This feature was added in an attempt to reduce the code size generated by the C18 compiler. While it did succeed in that goal, Microchip has deprecated the C18 compiler, and now supports only the XC8 compiler for 8-bit PICs. XC8 does not support the extended instruction set, and probably never will, meaning the extended instruction set is effectively obsolete.

    The extended instruction set is enabled/disabled with the configuration fuse bit XINST, which may be enabled by default on certain PICs. As a consequence, if XINST is not explicitly disabled, the PIC will operate in extended mode. Non-extended code running in extended mode will have various 'weird' behaviors that will depend on various factors, such as where the compiler happens to place objects in RAM. With XC8, extended mode should always be disabled with

    #pragma config XINST = OFF If you are using the free/lite/academic version of C18, it also does not support the extended instruction set, and it should be disabled as shown above. Only the paid version of C18 supports the extended instruction set. When the extended instruction set is enabled, it is also necessary to provide the --extended command-line option (or the equivalent in the IDE) to enable the generation of the appropriate code.
  • Why is the preprocessor calculating an incorrect value?

    It isn't. The preprocessor doesn't evaluate expressions in C code; it simply replaces macro(s) with their associated text. The compiler evaluates the resulting replaced text.

    There are two common errors when using the preprocessor to insert numeric expressions into code:

    1. Integer overflow: #define SECONDS_PER_DAY (60 * 60 * 24) long week = SECONDS_PER_DAY * 7; This expands to: long week = (60 * 60 * 24) * 7; The expected result is 604800, which fits easily into a long, but the actual result is something else. This is because the expression 60 * 60 * 24 is 86400, which does not fit into a 16-bit int, and thus overflows giving a garbage value. The fact that the result is being assigned to a long isn't relevant; 60 and 24 are ints, so the multiplication is done with int arithmetic. Use 60L to force long arithmetic.

      Note that MPLAB C18 has integer promotions disabled by default, which means expressions may be evaluated with char arithmetic, making overflows even more likely. You can enable integer promotions to get standard C behavior.

    2. Missing parentheses: #define CATS 2 #define DOGS 42 #define ANIMALS CATS + DOGS int pairs = ANIMALS / 2; This expands to: int pairs = 2 + 42 / 2; giving the unexpected result 23 instead of 22. Since the preprocessor does simple text substitution, ANIMAL is not any sort of , and doesn't get any special treatment when the compiler evaluates it. C's precedence rules cause the unexpected result. The fix is to always enclose expressions in parentheses: #define ANIMALS (CATS + DOGS) giving int pairs = (2 + 42) / 2;
  • Warnings are diagnostic messages that report constructions that are not inherently erroneous but that are risky or suggest there may have been an error.

    The following language-independent options do not enable specific warnings but control the kinds of diagnostics produced by GCC.

    You can request many specific warnings with options beginning with ‘’, for example to request warnings on implicit declarations. Each of these specific warning options also has a negative form beginning ‘’ to turn off warnings; for example, . This manual lists only one of the two forms, whichever is not the default. For further language-specific options also refer to C++ Dialect Options and Objective-C and Objective-C++ Dialect Options.

    Some options, such as and , turn on other options, such as , which may turn on further options, such as . The combined effect of positive and negative forms is that more specific options have priority over less specific ones, independently of their position in the command-line. For options of the same specificity, the last one takes effect. Options enabled or disabled via pragmas (see Diagnostic Pragmas) take effect as if they appeared at the end of the command-line.

    When an unrecognized warning option is requested (e.g., ), GCC emits a diagnostic stating that the option is not recognized. However, if the form is used, the behavior is slightly different: no diagnostic is produced for unless other diagnostics are being produced. This allows the use of new options with old compilers, but if something goes wrong, the compiler warns that an unrecognized option is present.

    Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any option used.

    Valid ISO C and ISO C++ programs should compile properly with or without this option (though a rare few require or a option specifying the required version of ISO C). However, without this option, certain GNU extensions and traditional C and C++ features are supported as well. With this option, they are rejected.

    does not cause warning messages for use of the alternate keywords whose names begin and end with ‘’. Pedantic warnings are also disabled in the expression that follows . However, only system header files should use these escape routes; application programs should avoid them. See Alternate Keywords.

    Some users try to use to check programs for strict ISO C conformance. They soon find that it does not do quite what they want: it finds some non-ISO practices, but not all—only those for which ISO C requires a diagnostic, and some others for which diagnostics have been added.

    A feature to report any failure to conform to ISO C might be useful in some instances, but would require considerable additional work and would be quite different from . We don’t have plans to support such a feature in the near future.

    Where the standard specified with represents a GNU extended dialect of C, such as ‘’ or ‘’, there is a corresponding base standard, the version of ISO C on which the GNU extended dialect is based. Warnings from are given where they are required by the base standard. (It does not make sense for such warnings to be given only for features not in the specified GNU C dialect, since by definition the GNU dialects of C include all features the compiler supports with the given option, and there would be nothing to warn about.)

    Give an error whenever the base standard (see ) requires a diagnostic, in some cases where there is undefined behavior at compile-time and in some other cases that do not prevent compilation of programs that are valid according to the standard. This is not equivalent to , since there are errors enabled by this option and not enabled by the latter and vice versa.

    This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros. This also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options.

    turns on the following warning flags:

    -Waddress -Warray-bounds=1 (only with) -Wbool-compare -Wbool-operation -Wc++11-compat -Wc++14-compat -Wcatch-value (C++ and Objective-C++ only) -Wchar-subscripts -Wcomment -Wduplicate-decl-specifier (C and Objective-C only) -Wenum-compare (in C/ObjC; this is on by default in C++) -Wformat -Wint-in-bool-context -Wimplicit (C and Objective-C only) -Wimplicit-int (C and Objective-C only) -Wimplicit-function-declaration (C and Objective-C only) -Winit-self (only for C++) -Wlogical-not-parentheses -Wmain (only for C/ObjC and unless) -Wmaybe-uninitialized -Wmemset-elt-size -Wmemset-transposed-args -Wmisleading-indentation (only for C/C++) -Wmissing-attributes -Wmissing-braces (only for C/ObjC) -Wmultistatement-macros -Wnarrowing (only for C++) -Wnonnull -Wnonnull-compare -Wopenmp-simd -Wparentheses -Wpointer-sign -Wreorder -Wrestrict -Wreturn-type -Wsequence-point -Wsign-compare (only in C++) -Wsizeof-pointer-div -Wsizeof-pointer-memaccess -Wstrict-aliasing -Wstrict-overflow=1 -Wswitch -Wtautological-compare -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunused-function -Wunused-label -Wunused-value -Wunused-variable -Wvolatile-register-var

    Note that some warning flags are not implied by . Some of them warn about constructions that users generally do not consider questionable, but which occasionally you might wish to check for; others warn about constructions that are necessary or hard to avoid in some cases, and there is no simple way to modify the code to suppress the warning. Some of them are enabled by but many of them must be enabled individually.

    This enables some extra warning flags that are not enabled by . (This option used to be called . The older name is still supported, but the newer name is more descriptive.)

    -Wclobbered -Wcast-function-type -Wempty-body -Wignored-qualifiers -Wimplicit-fallthrough=3 -Wmissing-field-initializers -Wmissing-parameter-type (C only) -Wold-style-declaration (C only) -Woverride-init -Wsign-compare (C only) -Wtype-limits -Wuninitialized -Wshift-negative-value (in C++03 and in C99 and newer) -Wunused-parameter (only withor) -Wunused-but-set-parameter (only withor)

    The option also prints warning messages for the following cases:

    • A pointer is compared against integer zero with , , , or .
    • (C++ only) An enumerator and a non-enumerator both appear in a conditional expression.
    • (C++ only) Ambiguous virtual bases.
    • (C++ only) Subscripting an array that has been declared .
    • (C++ only) Taking the address of a variable that has been declared .
    • (C++ only) A base class is not initialized in the copy constructor of a derived class.

    Warn if an array subscript has type . This is a common cause of error, as programmers often forget that this type is signed on some machines. This warning is enabled by .

    Warn about an invalid memory access that is found by Pointer Bounds Checker ().

    Warn if feedback profiles do not match when using the option. If a source file is changed between compiling with and with , the files with the profile feedback can fail to match the source file and GCC cannot use the profile feedback information. By default, this warning is enabled and is treated as an error. can be used to disable the warning or can be used to disable the error. Disabling the error for this warning can result in poorly optimized code and is useful only in the case of very minor changes such as bug fixes to an existing code-base. Completely disabling the warning is not recommended.

    (C, Objective-C, C++, Objective-C++ and Fortran only)

    Suppress warning messages emitted by directives.

    Give a warning when a value of type is implicitly promoted to . CPUs with a 32-bit “single-precision” floating-point unit implement in hardware, but emulate in software. On such a machine, doing computations using values is much more expensive because of the overhead required for software emulation.

    It is easy to accidentally do computations with because floating-point literals are implicitly of type . For example, in:

    float area(float radius) { return 3.14159 * radius * radius; }

    the compiler performs the entire computation with because the floating-point literal is a .

    Warn if a declaration has duplicate , , or specifier. This warning is enabled by .

    Check calls to and , etc., to make sure that the arguments supplied have types appropriate to the format string specified, and that the conversions specified in the format string make sense. This includes standard functions, and others specified by format attributes (see Function Attributes), in the , , and (an X/Open extension, not in the C standard) families (or other target-specific families). Which functions are checked without format attributes having been specified depends on the standard version selected, and such checks of functions without the attribute specified are disabled by or .

    The formats are checked against the format features supported by GNU libc version 2.2. These include all ISO C90 and C99 features, as well as features from the Single Unix Specification and some BSD and GNU extensions. Other library implementations may not support all these features; GCC does not support warning about features that go beyond a particular library’s limitations. However, if is used with , warnings are given about format features not in the selected standard version (but not for formats, since those are not in any version of the C standard). See Options Controlling C Dialect.

    Option is equivalent to , and is equivalent to . Since also checks for null format arguments for several functions, also implies . Some aspects of this level of format checking can be disabled by the options: , , and . is enabled by .

    If is specified, do not warn about format strings that contain NUL bytes.

    If is specified, do not warn about excess arguments to a or format function. The C standard specifies that such arguments are ignored.

    Where the unused arguments lie between used arguments that are specified with ‘’ operand number specifications, normally warnings are still given, since the implementation could not know what type to pass to to skip the unused arguments. However, in the case of formats, this option suppresses the warning if the unused arguments are all pointers, since the Single Unix Specification says that such unused arguments are allowed.

    Warn about calls to formatted input/output functions such as and that might overflow the destination buffer. When the exact number of bytes written by a format directive cannot be determined at compile-time it is estimated based on heuristics that depend on the argument and on optimization. While enabling optimization will in most cases improve the accuracy of the warning, it may also result in false positives.

    Level of enabled by employs a conservative approach that warns only about calls that most likely overflow the buffer. At this level, numeric arguments to format directives with unknown values are assumed to have the value of one, and strings of unknown length to be empty. Numeric arguments that are known to be bounded to a subrange of their type, or string arguments whose output is bounded either by their directive’s precision or by a finite set of string literals, are assumed to take on the value within the range that results in the most bytes on output. For example, the call to below is diagnosed because even with both and equal to zero, the terminating NUL character () appended by the function to the destination buffer will be written past its end. Increasing the size of the buffer by a single byte is sufficient to avoid the warning, though it may not be sufficient to avoid the overflow.

    void f (int a, int b) { char buf [13]; sprintf (buf, "a = %i, b = %i\n", a, b); }

    Level warns also about calls that might overflow the destination buffer given an argument of sufficient length or magnitude. At level , unknown numeric arguments are assumed to have the minimum representable value for signed types with a precision greater than 1, and the maximum representable value otherwise. Unknown string arguments whose length cannot be assumed to be bounded either by the directive’s precision, or by a finite set of string literals they may evaluate to, or the character array they may point to, are assumed to be 1 character long.

    At level , the call in the example above is again diagnosed, but this time because with equal to a 32-bit the first directive will write some of its digits beyond the end of the destination buffer. To make the call safe regardless of the values of the two variables, the size of the destination buffer must be increased to at least 34 bytes. GCC includes the minimum size of the buffer in an informational note following the warning.

    An alternative to increasing the size of the destination buffer is to constrain the range of formatted values. The maximum length of string arguments can be bounded by specifying the precision in the format directive. When numeric arguments of format directives can be assumed to be bounded by less than the precision of their type, choosing an appropriate length modifier to the format specifier will reduce the required buffer size. For example, if and in the example above can be assumed to be within the precision of the type then using either the format directive or casting the argument to reduces the maximum required size of the buffer to 24 bytes.

    void f (int a, int b) { char buf [23]; sprintf (buf, "a = %hi, b = %i\n", a, (short)b); }

    If is specified, do not warn about zero-length formats. The C standard specifies that zero-length formats are allowed.

    Enable plus additional format checks. Currently equivalent to .

    If is specified, also warn if the format string is not a string literal and so cannot be checked, unless the format function takes its format arguments as a .

    If is specified, also warn about uses of format functions that represent possible security problems. At present, this warns about calls to and functions where the format string is not a string literal and there are no format arguments, as in . This may be a security hole if the format string came from untrusted input and contains ‘’. (This is currently a subset of what warns about, but in future warnings may be added to that are not included in .)

    If is specified, also warn if the format string requires an unsigned argument and the argument is signed and vice versa.

    Warn about calls to formatted input/output functions such as and that might result in output truncation. When the exact number of bytes written by a format directive cannot be determined at compile-time it is estimated based on heuristics that depend on the argument and on optimization. While enabling optimization will in most cases improve the accuracy of the warning, it may also result in false positives. Except as noted otherwise, the option uses the same logic .

    Level of enabled by employs a conservative approach that warns only about calls to bounded functions whose return value is unused and that will most likely result in output truncation.

    Level warns also about calls to bounded functions whose return value is used and that might result in truncation given an argument of sufficient length or magnitude.

    If is specified, also warn about formats that may yield only a two-digit year.

    Warn about passing a null pointer for arguments marked as requiring a non-null value by the function attribute.

    is included in and . It can be disabled with the option.

    Warn when comparing an argument marked with the function attribute against null inside the function.

    is included in . It can be disabled with the option.

    Warn if the compiler detects paths that trigger erroneous or undefined behavior due to dereferencing a null pointer. This option is only active when is active, which is enabled by optimizations in most targets. The precision of the warnings depends on the optimization options used.

    Warn about uninitialized variables that are initialized with themselves. Note this option can only be used with the option.

    For example, GCC warns about being uninitialized in the following snippet only when has been specified:

    int f() { int i = i; return i; }

    This warning is enabled by in C++.

    Warn when a declaration does not specify a type. This warning is enabled by .

    Give a warning whenever a function is used before being declared. In C99 mode ( or ), this warning is enabled by default and it is made into an error by . This warning is also enabled by .

    Same as and . This warning is enabled by .

    is the same as and is the same as .

    Warn when a switch case falls through. For example:

    switch (cond) { case 1: a = 1; break; case 2: a = 2; case 3: a = 3; break; }

    This warning does not warn when the last statement of a case cannot fall through, e.g. when there is a return statement or a call to function declared with the noreturn attribute. also takes into account control flow statements, such as ifs, and only warns when appropriate. E.g.

    switch (cond) { case 1: if (i > 3) { bar (5); break; } else if (i < 1) { bar (0); } else return; default: … }

    Since there are occasions where a switch case fall through is desirable, GCC provides an attribute, , that is to be used along with a null statement to suppress this warning that would normally occur:

    switch (cond) { case 1: bar (0); __attribute__ ((fallthrough)); default: … }

    C++17 provides a standard way to suppress the warning using instead of the GNU attribute. In C++11 or C++14 users can use , which is a GNU extension. Instead of these attributes, it is also possible to add a fallthrough comment to silence the warning. The whole body of the C or C++ style comment should match the given regular expressions listed below. The option argument specifies what kind of comments are accepted:

    • disables the warning altogether.
    • matches regular expression, any comment is used as fallthrough comment.
    • case insensitively matches regular expression.
    • case sensitively matches one of the following regular expressions:
      • case sensitively matches one of the following regular expressions:
        • doesn’t recognize any comments as fallthrough comments, only attributes disable the warning.

        The comment needs to be followed after optional whitespace and other comments by or keywords or by a user label that precedes some or label.

        switch (cond) { case 1: bar (0); /* FALLTHRU */ default: … }

        The warning is enabled by .

        Control if warning triggered by the attribute should be issued. This is is enabled by default. Use to disable it.

        Warn if the return type of a function has a type qualifier such as . For ISO C such a type qualifier has no effect, since the value returned by a function is not an lvalue. For C++, the warning is only emitted for scalar types or . ISO C prohibits qualified return types on function definitions, so such return types always receive a warning even without this option.

        This warning is also enabled by .

        Warn when an attribute is ignored. This is different from the option in that it warns whenever the compiler decides to drop an attribute, not that the attribute is either unknown, used in a wrong place, etc. This warning is enabled by default.

        Warn if the type of is suspicious. should be a function with external linkage, returning int, taking either zero arguments, two, or three arguments of appropriate types. This warning is enabled by default in C++ and is enabled by either or .

        Warn when the indentation of the code does not reflect the block structure. Specifically, a warning is issued for , , , and clauses with a guarded statement that does not use braces, followed by an unguarded statement with the same indentation.

        In the following example, the call to “bar” is misleadingly indented as if it were guarded by the “if” conditional.

        if (some_condition ()) foo (); bar (); /* Gotcha: this is not guarded by the "if". */

        In the case of mixed tabs and spaces, the warning uses the option to determine if the statements line up (defaulting to 8).

        The warning is not issued for code involving multiline preprocessor logic such as the following example.

        if (flagA) foo (0); #if SOME_CONDITION_THAT_DOES_NOT_HOLD if (flagB) #endif foo (1);

        The warning is not issued after a directive, since this typically indicates autogenerated code, and no assumptions can be made about the layout of the file that the directive references.

        This warning is enabled by in C and C++.

        Warn when a declaration of a function is missing one or more attributes that a related function is declared with and whose absence may adversely affect the correctness or efficiency of generated code. For example, in C++, the warning is issued when an explicit specialization of a primary template declared with attribute , , , , , , or is declared without it. Attributes , , and suppress the warning. (see Function Attributes).

        is enabled by .

        For example, since the declaration of the primary function template below makes use of both attribute and the declaration of the explicit specialization of the template is diagnosed because it is missing one of the attributes.

        template <class T> T* __attribute__ ((malloc, alloc_size (1))) allocate (size_t); template <> void* __attribute__ ((malloc)) // missing alloc_size allocate<void> (size_t);

        Warn if an aggregate or union initializer is not fully bracketed. In the following example, the initializer for is not fully bracketed, but that for is fully bracketed. This warning is enabled by in C.

        int a[2][2] = { 0, 1, 2, 3 }; int b[2][2] = { { 0, 1 }, { 2, 3 } };

        This warning is enabled by .

        Warn if a user-supplied include directory does not exist.

        Warn about unsafe multiple statement macros that appear to be guarded by a clause such as , , , , or , in which only the first statement is actually guarded after the macro is expanded.

        For example:

        #define DOIT x++; y++ if (c) DOIT;

        will increment unconditionally, not just when holds. The can usually be fixed by wrapping the macro in a do-while loop:

        #define DOIT do { x++; y++; } while (0) if (c) DOIT;

        This warning is enabled by in C and C++.

        Warn if parentheses are omitted in certain contexts, such as when there is an assignment in a context where a truth value is expected, or when operators are nested whose precedence people often get confused about.

        Also warn if a comparison like appears; this is equivalent to , which is a different interpretation from that of ordinary mathematical notation.

        Also warn for dangerous uses of the GNU extension to with omitted middle operand. When the condition in the : operator is a boolean expression, the omitted value is always 1. Often programmers expect it to be a value computed inside the conditional expression instead.

        For C++ this also warns for some cases of unnecessary parentheses in declarations, which can indicate an attempt at a function call instead of a declaration:

        { // Declares a local variable called mymutex. std::unique_lock<std::mutex> (mymutex); // User meant std::unique_lock<std::mutex> lock (mymutex); }

        This warning is enabled by .

        Warn about code that may have undefined semantics because of violations of sequence point rules in the C and C++ standards.

        The C and C++ standards define the order in which expressions in a C/C++ program are evaluated in terms of sequence points, which represent a partial ordering between the execution of parts of the program: those executed before the sequence point, and those executed after it. These occur after the evaluation of a full expression (one which is not part of a larger expression), after the evaluation of the first operand of a , , or (comma) operator, before a function is called (but after the evaluation of its arguments and the expression denoting the called function), and in certain other places. Other than as expressed by the sequence point rules, the order of evaluation of subexpressions of an expression is not specified. All these rules describe only a partial order rather than a total order, since, for example, if two functions are called within one expression with no sequence point between them, the order in which the functions are called is not specified. However, the standards committee have ruled that function calls do not overlap.

        It is not specified when between sequence points modifications to the values of objects take effect. Programs whose behavior depends on this have undefined behavior; the C and C++ standards specify that “Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.”. If a program breaks these rules, the results on any particular implementation are entirely unpredictable.

        Examples of code with undefined behavior are , and . Some more complicated cases are not diagnosed by this option, and it may give an occasional false positive result, but in general it has been found fairly effective at detecting this sort of problem in programs.

        The C++17 standard will define the order of evaluation of operands in more cases: in particular it requires that the right-hand side of an assignment be evaluated before the left-hand side, so the above examples are no longer undefined. But this warning will still warn about them, to help people avoid writing code that is undefined in C and earlier revisions of C++.

        The standard is worded confusingly, therefore there is some debate over the precise meaning of the sequence point rules in subtle cases. Links to discussions of the problem, including proposed formal definitions, may be found on the GCC readings page, at http://gcc.gnu.org/readings.html.

        This warning is enabled by for C and C++.

        Do not warn about returning a pointer (or in C++, a reference) to a variable that goes out of scope after the function returns.

        Warn whenever a function is defined with a return type that defaults to . Also warn about any statement with no return value in a function whose return type is not (falling off the end of the function body is considered returning without a value).

        For C only, warn about a statement with an expression in a function whose return type is , unless the expression type is also . As a GNU extension, the latter case is accepted without a warning unless is used.

        For C++, a function without return type always produces a diagnostic message, even when is specified. The only exceptions are and functions defined in system headers.

        This warning is enabled by .

        Warn if shift count is negative. This warning is enabled by default.

        Warn if shift count >= width of type. This warning is enabled by default.

        Warn if left shifting a negative value. This warning is enabled by in C99 and C++11 modes (and newer).

        Warn about left shift overflows. This warning is enabled by default in C99 and C++11 modes (and newer).

        This is the warning level of and is enabled by default in C99 and C++11 modes (and newer). This warning level does not warn about left-shifting 1 into the sign bit. (However, in C, such an overflow is still rejected in contexts where an integer constant expression is required.)

        This warning level also warns about left-shifting 1 into the sign bit, unless C++14 mode is active.

        Warn whenever a statement has an index of enumerated type and lacks a for one or more of the named codes of that enumeration. (The presence of a label prevents this warning.) labels outside the enumeration range also provoke warnings when this option is used (even if there is a label). This warning is enabled by .

        Warn whenever a statement does not have a case.

        Warn whenever a statement has an index of enumerated type and lacks a for one or more of the named codes of that enumeration. labels outside the enumeration range also provoke warnings when this option is used. The only difference between and this option is that this option gives a warning about an omitted enumeration code even if there is a label.

        Warn whenever a statement has an index of boolean type and the case values are outside the range of a boolean type. It is possible to suppress this warning by casting the controlling expression to a type other than . For example:

        switch ((int) (a == 4)) { … }

        This warning is enabled by default for C and C++ programs.

        Warn whenever a statement contains statements between the controlling expression and the first case label, which will never be executed. For example:

        switch (cond) { i = 15; … case 5: … }

        does not warn if the statement between the controlling expression and the first case label is just a declaration:

        switch (cond) { int i; … case 5: i = 5; … }

        This warning is enabled by default for C and C++ programs.

        Warn when and built-in functions are used. These functions changed semantics in GCC 4.4.

        Warn whenever a function parameter is assigned to, but otherwise unused (aside from its declaration).

        To suppress this warning use the attribute (see Variable Attributes).

        This warning is also enabled by together with .

        Warn whenever a local variable is assigned to, but otherwise unused (aside from its declaration). This warning is enabled by .

        To suppress this warning use the attribute (see Variable Attributes).

        This warning is also enabled by , which is enabled by .

        Warn whenever a static function is declared but not defined or a non-inline static function is unused. This warning is enabled by .

        Warn whenever a label is declared but not used. This warning is enabled by .

        To suppress this warning use the attribute (see Variable Attributes).

        Warn when a typedef locally defined in a function is not used. This warning is enabled by .

        Warn whenever a function parameter is unused aside from its declaration.

        To suppress this warning use the attribute (see Variable Attributes).

        Do not warn if a caller of a function marked with attribute (see Function Attributes) does not use its return value. The default is .

        Warn whenever a local or static variable is unused aside from its declaration. This option implies for C, but not for C++. This warning is enabled by .

        To suppress this warning use the attribute (see Variable Attributes).

        Warn whenever a constant static variable is unused aside from its declaration. is enabled by for C, but not for C++. In C this declares variable storage, but in C++ this is not an error since const variables take the place of s.

        To suppress this warning use the attribute (see Variable Attributes).

        This is the warning level that is enabled by for C. It warns only about unused static const variables defined in the main compilation unit, but not about static const variables declared in any header included.

        This warning level also warns for unused constant static variables in headers (excluding system headers). This is the warning level of and must be explicitly requested since in C++ this isn’t an error and in C it might be harder to clean up all headers included.

        Warn whenever a statement computes a result that is explicitly not used. To suppress this warning cast the unused expression to . This includes an expression-statement or the left-hand side of a comma expression that contains no side effects. For example, an expression such as causes a warning, while does not.

        This warning is enabled by .

        All the above options combined.

        In order to get a warning about an unused function parameter, you must either specify (note that implies ), or separately specify .

        Warn if an automatic variable is used without first being initialized or if a variable may be clobbered by a call. In C++, warn if a non-static reference or non-static member appears in a class without constructors.

        If you want to warn about code that uses the uninitialized value of the variable in its own initializer, use the option.

        These warnings occur for individual uninitialized or clobbered elements of structure, union or array variables as well as for variables that are uninitialized or clobbered as a whole. They do not occur for variables or elements declared . Because these warnings depend on optimization, the exact variables or elements for which there are warnings depends on the precise optimization options and version of GCC used.

        Note that there may be no warning about a variable that is used only to compute a value that itself is never used, because such computations may be deleted by data flow analysis before the warnings are printed.

        Warn for invocations of __atomic Builtins, __sync Builtins, and the C11 atomic generic functions with a memory consistency argument that is either invalid for the operation or outside the range of values of the enumeration. For example, since the and built-ins are only defined for the relaxed, release, and sequentially consistent memory orders the following code is diagnosed:

        void store (int *i) { __atomic_store_n (i, 0, memory_order_consume); }

        is enabled by default.

        For an automatic (i.e. local) variable, if there exists a path from the function entry to a use of the variable that is initialized, but there exist some other paths for which the variable is not initialized, the compiler emits a warning if it cannot prove the uninitialized paths are not executed at run time.

        These warnings are only possible in optimizing compilation, because otherwise GCC does not keep track of the state of variables.

        These warnings are made optional because GCC may not be able to determine when the code is correct in spite of appearing to have an error. Here is one example of how this can happen:

        { int x; switch (y) { case 1: x = 1; break; case 2: x = 4; break; case 3: x = 5; } foo (x); }

        If the value of is always 1, 2 or 3, then is always initialized, but GCC doesn’t know this. To suppress the warning, you need to provide a default case with assert(0) or similar code.

        This option also warns when a non-volatile automatic variable might be changed by a call to . The compiler sees only the calls to . It cannot know where will be called; in fact, a signal handler could call it at any point in the code. As a result, you may get a warning even when there is in fact no problem because cannot in fact be called at the place that would cause a problem.

        Some spurious warnings can be avoided if you declare all the functions you use that never return as . See Function Attributes.

        This warning is enabled by or .

        Warn when a directive is encountered that is not understood by GCC. If this command-line option is used, warnings are even issued for unknown pragmas in system header files. This is not the case if the warnings are only enabled by the command-line option.

        Do not warn about misuses of pragmas, such as incorrect parameters, invalid syntax, or conflicts between pragmas. See also .

        This option is only active when is active. It warns about code that might break the strict aliasing rules that the compiler is using for optimization. The warning does not catch all cases, but does attempt to catch the more common pitfalls. It is included in . It is equivalent to

        This option is only active when is active. It warns about code that might break the strict aliasing rules that the compiler is using for optimization. Higher levels correspond to higher accuracy (fewer false positives). Higher levels also correspond to more effort, similar to the way works. is equivalent to .

        Level 1: Most aggressive, quick, least accurate. Possibly useful when higher levels do not warn but still breaks the code, as it has very few false negatives. However, it has many false positives. Warns for all pointer conversions between possibly incompatible types, even if never dereferenced. Runs in the front end only.

        Level 2: Aggressive, quick, not too precise. May still have many false positives (not as many as level 1 though), and few false negatives (but possibly more than level 1). Unlike level 1, it only warns when an address is taken. Warns about incomplete types. Runs in the front end only.

        Level 3 (default for ): Should have very few false positives and few false negatives. Slightly slower than levels 1 or 2 when optimization is enabled. Takes care of the common pun+dereference pattern in the front end: . If optimization is enabled, it also runs in the back end, where it deals with multiple statement cases using flow-sensitive points-to information. Only warns when the converted pointer is dereferenced. Does not warn about incomplete types.

        This option is only active when signed overflow is undefined. It warns about cases where the compiler optimizes based on the assumption that signed overflow does not occur. Note that it does not warn about all cases where the code might overflow: it only warns about cases where the compiler implements some optimization. Thus this warning depends on the optimization level.

        An optimization that assumes that signed overflow does not occur is perfectly safe if the values of the variables involved are such that overflow never does, in fact, occur. Therefore this warning can easily give a false positive: a warning about code that is not actually a problem. To help focus on important issues, several warning levels are defined. No warnings are issued for the use of undefined signed overflow when estimating how many iterations a loop requires, in particular when determining whether a loop will be executed at all.

        Warn about cases that are both questionable and easy to avoid. For example the compiler simplifies to . This level of is enabled by ; higher levels are not, and must be explicitly requested.

        Also warn about other cases where a comparison is simplified to a constant. For example: . This can only be simplified when signed integer overflow is undefined, because overflows to , which is less than zero. (with no level) is the same as .

        Also warn about other cases where a comparison is simplified. For example: is simplified to .

        Also warn about other simplifications not covered by the above cases. For example: is simplified to .

        Also warn about cases where the compiler reduces the magnitude of a constant involved in a comparison. For example: is simplified to . This is reported only at the highest warning level because this simplification applies to many comparisons, so this warning level gives a very large number of false positives.

        Warn for calls to string manipulation functions such as and that are determined to overflow the destination buffer. The optional argument is one greater than the type of Object Size Checking to perform to determine the size of the destination. See Object Size Checking. The argument is meaningful only for functions that operate on character arrays but not for raw memory functions like which always make use of Object Size type-0. The option also warns for calls that specify a size in excess of the largest possible object or at most bytes. The option produces the best results with optimization enabled but can detect a small subset of simple buffer overflows even without optimization in calls to the GCC built-in functions like that correspond to the standard functions. In any case, the option warns about just a subset of buffer overflows detected by the corresponding overflow checking built-ins. For example, the option will issue a warning for the call below because it copies at least 5 characters (the string including the terminating NUL) into the buffer of size 4.

        enum Color { blue, purple, yellow }; const char* f (enum Color clr) { static char buf [4]; const char *str; switch (clr) { case blue: str = "blue"; break; case purple: str = "purple"; break; case yellow: str = "yellow"; break; } return strcpy (buf, str); // warning here }

        Option is enabled by default.

        The option uses type-zero Object Size Checking to determine the sizes of destination objects. This is the default setting of the option. At this setting the option will not warn for writes past the end of subobjects of larger objects accessed by pointers unless the size of the largest surrounding object is known. When the destination may be one of several objects it is assumed to be the largest one of them. On Linux systems, when optimization is enabled at this setting the option warns for the same code as when the macro is defined to a non-zero value.

        The option uses type-one Object Size Checking to determine the sizes of destination objects. At this setting the option will warn about overflows when writing to members of the largest complete objects whose exact size is known. It will, however, not warn for excessive writes to the same members of unknown objects referenced by pointers since they may point to arrays containing unknown numbers of elements.

        The option uses type-two Object Size Checking to determine the sizes of destination objects. At this setting the option warns about overflowing the smallest object or data member. This is the most restrictive setting of the option that may result in warnings for safe code.

        The option uses type-three Object Size Checking to determine the sizes of destination objects. At this setting the option will warn about overflowing any data members, and when the destination is one of several objects it uses the size of the largest of them to decide whether to issue a warning. Similarly to this setting of the option may result in warnings for benign code.

        Warn for calls to bounded string manipulation functions such as , , and that may either truncate the copied string or leave the destination unchanged.

        In the following example, the call to specifies a bound that is less than the length of the source string. As a result, the copy of the source will be truncated and so the call is diagnosed. To avoid the warning use as the bound.

        void append (char *buf, size_t bufsize) { strncat (buf, ".txt", 3); }

        As another example, the following call to results in copying to just the characters preceding the terminating NUL, without appending the NUL to the end. Assuming the result of is necessarily a NUL-terminated string is a common mistake, and so the call is diagnosed. To avoid the warning when the result is not expected to be NUL-terminated, call instead.

        void copy (char *d, const char *s) { strncpy (d, s, strlen (s)); }

        In the following example, the call to specifies the size of the destination buffer as the bound. If the length of the source string is equal to or greater than this size the result of the copy will not be NUL-terminated. Therefore, the call is also diagnosed. To avoid the warning, specify as the bound and set the last element of the buffer to .

        void copy (const char *s) { char buf[80]; strncpy (buf, s, sizeof buf); … }

        In situations where a character array is intended to store a sequence of bytes with no terminating such an array may be annotated with attribute to avoid this warning. Such arrays, however, are not suitable arguments to functions that expect -terminated strings. To help detect accidental misuses of such arrays GCC issues warnings unless it can prove that the use is safe. See Common Variable Attributes.

        Warn for cases where adding an attribute may be beneficial. The attributes currently supported are listed below.

        Warn about functions that might be candidates for attributes , or or . The compiler only warns for functions visible in other compilation units or (in the case of and ) if it cannot prove that the function returns normally. A function returns normally if it doesn’t contain an infinite loop or return abnormally by throwing, calling or trapping. This analysis requires option , which is enabled by default at and higher. Higher optimization levels improve the accuracy of the analysis.

        Warn about function pointers that might be candidates for attributes. Note these are only possible candidates, not absolute ones. GCC guesses that function pointers with attributes that are used in assignment, initialization, parameter passing or return statements should have a corresponding attribute in the resulting type. I.e. the left-hand side of the assignment or initialization, the type of the parameter variable, or the return type of the containing function respectively should also have a attribute to avoid the warning.

        GCC also warns about function definitions that might be candidates for attributes. Again, these are only possible candidates. GCC guesses that attributes might be appropriate for any function that calls a function like or , but this might not always be the case, and some functions for which attributes are appropriate may not be detected.

        Warn about functions that might be candidates for attribute. This is based on static detection and generally will only warn about functions which always leads to a call to another function such as wrappers of C++ or fatal error reporting functions leading to .

        Warn about types with virtual methods where code quality would be improved if the type were declared with the C++11 specifier, or, if possible, declared in an anonymous namespace. This allows GCC to more aggressively devirtualize the polymorphic calls. This warning is more effective with link time optimization, where the information about the class hierarchy graph is more complete.

        Warn about virtual methods where code quality would be improved if the method were declared with the C++11 specifier, or, if possible, its type were declared in an anonymous namespace or with the specifier. This warning is more effective with link-time optimization, where the information about the class hierarchy graph is more complete. It is recommended to first consider suggestions of and then rebuild with new annotations.

        Warn about overriding virtual functions that are not marked with the override keyword.

        Warn about calls to allocation functions decorated with attribute that specify zero bytes, including those to the built-in forms of the functions , , , , and . Because the behavior of these functions when called with a zero size differs among implementations (and in the case of has been deprecated) relying on it may result in subtle portability bugs and should be avoided.

        Warn about calls to functions decorated with attribute that attempt to allocate objects larger than the specified number of bytes, or where the result of the size computation in an integer type with infinite precision would exceed . The option argument may end in one of the standard suffixes designating a multiple of bytes such as and for kilobyte and kibibyte, respectively, and for megabyte and mebibyte, and so on. See Function Attributes.

        This option warns on all uses of in the source.

        This option warns on calls to that are not bounded by a controlling predicate limiting its argument of integer type to at most bytes, or calls to where the bound is unknown. Arguments of non-integer types are considered unbounded even if they appear to be constrained to the expected range.

        For example, a bounded case of could be:

        void func (size_t n) { void *p; if (n <= 1000) p = alloca (n); else p = malloc (n); f (p); }

        In the above example, passing would not issue a warning because the call to is known to be at most 1000 bytes. However, if were passed, the compiler would emit a warning.

        Unbounded uses, on the other hand, are uses of with no controlling predicate constraining its integer argument. For example:

        void func () { void *p = alloca (n); f (p); }

        If were passed, the above would trigger a warning, but this time because of the lack of bounds checking.

        Note, that even seemingly correct code involving signed integers could cause a warning:

        void func (signed int n) { if (n < 500) { p = alloca (n); f (p); } }

        In the above example, could be negative, causing a larger than expected argument to be implicitly cast into the call.

        This option also warns when is used in a loop.

        This warning is not enabled by , and is only active when is active (default for and above).

        See also .

        This option is only active when is active (default for and above). It warns about subscripts to arrays that are always out of bounds. This warning is enabled by .

        This is the warning level of and is enabled by ; higher levels are not, and must be explicitly requested.

        This warning level also warns about out of bounds access for arrays at the end of a struct and for arrays accessed through pointers. This warning level may give a larger number of false positives and is deactivated by default.

        Warn about declarations using the and similar attributes whose target is incompatible with the type of the alias. See Declaring Attributes of Functions.

        Warn about boolean expression compared with an integer value different from /. For instance, the following comparison is always false:

        int n = 5; … if ((n > 1) == 2) { … }

        This warning is enabled by .

        Warn about suspicious operations on expressions of a boolean type. For instance, bitwise negation of a boolean is very likely a bug in the program. For C, this warning also warns about incrementing or decrementing a boolean, which rarely makes sense. (In C++, decrementing a boolean is always invalid. Incrementing a boolean is invalid in C++17, and deprecated otherwise.)

        This warning is enabled by .

        Warn when an if-else has identical branches. This warning detects cases like

        if (p != NULL) return 0; else return 0;

        It doesn’t warn when both branches contain just a null statement. This warning also warn for conditional operators:

        Warn about duplicated conditions in an if-else-if chain. For instance, warn for the following code:

        if (p->q != NULL) { … } else if (p->q != NULL) { … }

        Warn when the ‘’ or ‘’ is called with an argument greater than 0. Such calls may return indeterminate values or crash the program. The warning is included in .

        Do not warn if type qualifiers on pointers are being discarded. Typically, the compiler warns if a variable is passed to a function that takes a parameter. This option can be used to suppress such a warning.

        Do not warn if type qualifiers on arrays which are pointer targets are being discarded. Typically, the compiler warns if a variable is passed to a function that takes a parameter. This option can be used to suppress such a warning.

        Do not warn when there is a conversion between pointers that have incompatible types. This warning is for cases not covered by , which warns for pointer argument passing or assignment with different signedness.

        Do not warn about incompatible integer to pointer and pointer to integer conversions. This warning is about implicit conversions; for explicit conversions the warnings and may be used.

        Do not warn about compile-time integer division by zero. Floating-point division by zero is not warned about, as it can be a legitimate way of obtaining infinities and NaNs.

        Print warning messages for constructs found in system header files. Warnings from system headers are normally suppressed, on the assumption that they usually do not indicate real problems and would only make the compiler output harder to read. Using this command-line option tells GCC to emit warnings from system headers as if they occurred in user code. However, note that using in conjunction with this option does not warn about unknown pragmas in system headers—for that, must also be used.

        Warn if a self-comparison always evaluates to true or false. This warning detects various mistakes such as:

        int i = 1; … if (i > i) { … }

        This warning also warns about bitwise comparisons that always evaluate to true or false, for instance:

        if ((a & 16) == 10) { … }

        will always be false.

        This warning is enabled by .

        Warn about trampolines generated for pointers to nested functions. A trampoline is a small piece of data or code that is created at run time on the stack when the address of a nested function is taken, and is used to call the nested function indirectly. For some targets, it is made up of data only and thus requires no special treatment. But, for most targets, it is made up of code and thus requires the stack to be made executable in order for the program to work properly.

        Warn if floating-point values are used in equality comparisons.

        The idea behind this is that sometimes it is convenient (for the programmer) to consider floating-point values as approximations to infinitely precise real numbers. If you are doing this, then you need to compute (by analyzing the code, or in some other way) the maximum or likely maximum error that the computation introduces, and allow for it when performing comparisons (and when producing output, but that’s a different problem). In particular, instead of testing for equality, you should check to see whether the two values have ranges that overlap; and this is done with the relational operators, so equality comparisons are probably mistaken.

        Warn about certain constructs that behave differently in traditional and ISO C. Also warn about ISO C constructs that have no traditional C equivalent, and/or problematic constructs that should be avoided.

        • Macro parameters that appear within string literals in the macro body. In traditional C macro replacement takes place within string literals, but in ISO C it does not.
        • In traditional C, some preprocessor directives did not exist. Traditional preprocessors only considered a line to be a directive if the ‘’ appeared in column 1 on the line. Therefore warns about directives that traditional C understands but ignores because the ‘’ does not appear as the first character on the line. It also suggests you hide directives like not understood by traditional C by indenting them. Some traditional implementations do not recognize , so this option suggests avoiding it altogether.
        • A function-like macro that appears without arguments.
        • The unary plus operator.
        • The ‘’ integer constant suffix, or the ‘’ or ‘’ floating-point constant suffixes. (Traditional C does support the ‘’ suffix on integer constants.) Note, these suffixes appear in macros defined in the system headers of most modern systems, e.g. the ‘’/‘’ macros in . Use of these macros in user code might normally lead to spurious warnings, however GCC’s integrated preprocessor has enough context to avoid warning in these cases.
        • A function declared external in one block and then used after the end of the block.
        • A statement has an operand of type .
        • A non- function declaration follows a one. This construct is not accepted by some traditional C compilers.
        • The ISO type of an integer constant has a different width or signedness from its traditional type. This warning is only issued if the base of the constant is ten. I.e. hexadecimal or octal values, which typically represent bit patterns, are not warned about.
        • Usage of ISO string concatenation is detected.
        • Initialization of automatic aggregates.
        • Identifier conflicts with labels. Traditional C lacks a separate namespace for labels.
        • Initialization of unions. If the initializer is zero, the warning is omitted. This is done under the assumption that the zero initializer in user code appears conditioned on e.g. to avoid missing initializer warnings and relies on default initialization to zero in the traditional C case.
        • Conversions by prototypes between fixed/floating-point values and vice versa. The absence of these prototypes when compiling with traditional C causes serious problems. This is a subset of the possible conversion warnings; for the full set use .
        • Use of ISO C style function definitions. This warning intentionally is not issued for prototype declarations or variadic functions because these ISO C features appear in your code when using libiberty’s traditional C compatibility macros, and . This warning is also bypassed for nested functions because that feature is already a GCC extension and thus not relevant to traditional C compatibility.

        Warn if a prototype causes a type conversion that is different from what would happen to the same argument in the absence of a prototype. This includes conversions of fixed point to floating and vice versa, and conversions changing the width or signedness of a fixed-point argument except when the same as the default promotion.

        Warn when a declaration is found after a statement in a block. This construct, known from C++, was introduced with ISO C99 and is by default allowed in GCC. It is not supported by ISO C90. See Mixed Declarations.

        Warn whenever a local variable or type declaration shadows another variable, parameter, type, class member (in C++), or instance variable (in Objective-C) or whenever a built-in function is shadowed. Note that in C++, the compiler warns if a local variable shadows an explicit typedef, but not if it shadows a struct/class/enum. Same as .

        Do not warn whenever a local variable shadows an instance variable in an Objective-C method.

        The default for . Warns for any (global) shadowing.

        Warn when a local variable shadows another local variable or parameter. This warning is enabled by .

        Warn when a local variable shadows another local variable or parameter whose type is compatible with that of the shadowing variable. In C++, type compatibility here means the type of the shadowing variable can be converted to that of the shadowed variable. The creation of this flag (in addition to ) is based on the idea that when a local variable shadows another one of incompatible type, it is most likely intentional, not a bug or typo, as shown in the following example:

        for (SomeIterator i = SomeObj.begin(); i != SomeObj.end(); ++i) { for (int i = 0; i < N; ++i) { ... } ... }

        Since the two variable in the example above have incompatible types, enabling only will not emit a warning. Because their types are incompatible, if a programmer accidentally uses one in place of the other, type checking will catch that and emit an error or warning. So not warning (about shadowing) in this case will not lead to undetected bugs. Use of this flag instead of can possibly reduce the number of warnings triggered by intentional shadowing.

        This warning is enabled by .

        Warn whenever an object of larger than bytes is defined.

        Warn if the size of a function frame is larger than bytes. The computation done to determine the stack frame size is approximate and not conservative. The actual requirements may be somewhat greater than even if you do not get a warning. In addition, any space allocated via , variable-length arrays, or related constructs is not included by the compiler when determining whether or not to issue a warning.

        Do not warn when attempting to free an object that was not allocated on the heap.

        Warn if the stack usage of a function might be larger than bytes. The computation done to determine the stack usage is conservative. Any space allocated via , variable-length arrays, or related constructs is included by the compiler when determining whether or not to issue a warning.

        The message is in keeping with the output of .

        • If the stack usage is fully static but exceeds the specified amount, it’s:
          warning: stack usage is 1120 bytes
        • If the stack usage is (partly) dynamic but bounded, it’s:
          warning: stack usage might be 1648 bytes
        • If the stack usage is (partly) dynamic and not bounded, it’s:
          warning: stack usage might be unbounded

        Warn if the loop cannot be optimized because the compiler cannot assume anything on the bounds of the loop indices. With warn if the compiler makes such assumptions.

        When used in combination with and without GNU extensions, this option disables the warnings about non-ISO / format width specifiers , , and used on Windows targets, which depend on the MS runtime.

        0 comments

        Leave a Reply

        Your email address will not be published. Required fields are marked *