message "excess elements in array initializer"

Thread Starter

King2

Joined Jul 17, 2022
163
You can create a structure x which contains different data types.
I think, You didn't understand my question completely. my question was for rules of c language.

My first question was why can't we write two data types for one variable in the program, which is answered by WBahn.

My second question was that why we can't have two storage classes for one variable the reason I have explained it but I don't know whether it is right or wrong.
 

MrChips

Joined Oct 2, 2009
34,814
The compiler needs to reserve storage for data.

The storage required for a char is different from that of an int.
Creating a structure allows one to reserve different data types under the same name.

You can use the same storage for different purposes using a union.
 

WBahn

Joined Mar 31, 2012
32,840
Thanks for clearing the doubts. I wrote code with two storage classes and one variable. Experiment show that we cannot have two storages with one variable.

Why we can't have two storages with one variable. What is the purpose of the C language creators behind this rule?

I think the reason is that if there are two storage classes then the compiler will get confused where to store the variable
Not just the compiler. Look at my example. What is the final value of x after the assignment? Is it 2 or is it 'L'.

Having the same name for two different things causes problems in everyday contexts, too. We've all experienced this when we are in a group of people and two of them have the same first name.

One thing that C has, which are seldom used and, when they are, are often abused and cause problems, are unions whereby you have essentially the opposite, multiple variable identifiers and storage classes associated with the same storage space. This can be a very powerful and useful tool, if used judiciously, but it makes it impossible for the compiler to enforce good typing.
 

nsaspook

Joined Aug 27, 2009
16,325
Not just the compiler. Look at my example. What is the final value of x after the assignment? Is it 2 or is it 'L'.

Having the same name for two different things causes problems in everyday contexts, too. We've all experienced this when we are in a group of people and two of them have the same first name.

One thing that C has, which are seldom used and, when they are, are often abused and cause problems, are unions whereby you have essentially the opposite, multiple variable identifiers and storage classes associated with the same storage space. This can be a very powerful and useful tool, if used judiciously, but it makes it impossible for the compiler to enforce good typing.
The times you really need unions to clarify software are typically with arbitrary hardware interfaces to I/O devices. If you need to transform a untyped bit-based interface into the typed C structured universe with unions it will likely be system and and hardware dependant (like a 24-bit adc buffer, index and control bits) on a few levels.
C:
/* for 24-bit transmit and extra status data */
typedef struct A_data {
    uint32_t dummy12 : 12; // dummy space for adc data
    uint32_t nullbits : 2;
    uint32_t index : 3; //adc channel select
    uint32_t single_diff : 1;
    uint32_t start_bit : 1;
    uint32_t dummy8 : 8;
    uint32_t finish : 1;
    uint32_t in_progress : 1;
} A_data;

/* upper-> lower bytes to 32 bit word for ADC/DAC, etc ... */
union bytes4 {
    uint32_t ld;
    uint8_t bd[4];
};

/* upper/lower bytes to 16 bit word for ADC/DAC, etc ... */
union bytes2 {
    uint16_t ld;
    uint8_t bd[2];
};

/* used to hold 24-bit adc buffer, index and control bits */
union adc_buf_type {
    uint32_t ld;
    uint8_t bd[4];
    struct A_data map;
};

typedef struct {
    union adc_buf_type mcp3208_cmd;
    uint16_t potValue;
    uint8_t chan;
} ADC_DATA;
C:
void ADC_Init()
{
    adcData.mcp3208_cmd.ld = 0; // clear the command word
    adcData.chan = 0;
    adcData.mcp3208_cmd.map.start_bit = 1;
    adcData.mcp3208_cmd.map.single_diff = 1;
    adcData.mcp3208_cmd.map.index = 0; // channel
    appData.ADCcalFlag = true;
    SPI_CS0 = 1;
}

//State machine for restarting ADC and taking new readings from pot
//Returns true when SPI data has been returned from the mpc3208; false otherwise

bool ADC_Tasks(void)
{
    static uint8_t count = 0;

    /* send the command sequence to the adc */
    if (!adcData.mcp3208_cmd.map.in_progress) {
        adcData.mcp3208_cmd.map.in_progress = true;
        adcData.mcp3208_cmd.map.finish = false;
        count = 0;
        if (!SPI_IsTxData()) {
            adcData.mcp3208_cmd.map.single_diff = 1;
            adcData.mcp3208_cmd.map.index = adcData.chan;
            SPI_ClearBufs(); // dump the spi buffers
            SPI_WriteTxBuffer(adcData.mcp3208_cmd.bd[2]);
            SPI_WriteTxBuffer(adcData.mcp3208_cmd.bd[1]);
            SPI_WriteTxBuffer(adcData.mcp3208_cmd.bd[0]);
            SPI_CS0 = 0; // select the ADC
            SPI_Speed(0);
            SPI_TxStart();
        }
        return false;
    }

    /* read the returned spi data from the buffer and format it */
    if (adcData.mcp3208_cmd.map.in_progress) {
        while (SPI_IsNewRxData()) {
            switch (count) {
            case 1:
                adcData.potValue = (SPI_ReadRxBuffer()&0x0f) << 8;
                break;
            case 2:
                adcData.potValue += SPI_ReadRxBuffer();
                adcData.mcp3208_cmd.map.finish = true;
                break;
            default:
                SPI_ReadRxBuffer(); // eat extra bytes
                break;
            }
            count++;
        }
    }

    /* cleanup for next time */
    if (adcData.mcp3208_cmd.map.finish) {
        adcData.mcp3208_cmd.map.in_progress = false;
        appData.accumReady = true;
        return true;
    }

    return false;
}

//Process the accumulator value once it is ready
//And update stored potentiometer values

void ADC_ProcAccum(void)
{
    appData.potValueOld = appData.potValue; //Save previous value
    appData.potValue = adcData.potValue;
}

//ADC ISR

void _ISR_NO_AUTO_PSV _ISR _ADC1Interrupt(void)
{
    IFS0bits.AD1IF = 0;
    //Accumulation complete

}

void GetNewADC_Chan(void)
{
    adcData.chan = appData.receive_packet[9] == '1' ? 1 : 0; // update adc channel 
    adcData.chan += appData.receive_packet[11] == '1' ? 2 : 0;
    adcData.chan += appData.receive_packet[13] == '1' ? 4 : 0;
}
 
Top