Reading/writing to Arduino GPIO pins from raw C code
In theses cases you are right, using register address is the way to read/write data from/to digital pins.
In the case you use analog input, the process is similar but you have to follow some procedures before getting the value of the data.

GPIO REGISTERS

For AVR micro-controllers these registers are:
DDRn – Data Direction Register
PORTn – Port Output data Register
PINn – Port Input Register
n- Indicates the port name i.e. A, B, C &amp; D
If you have arduino board and want to use these pins, look for mapping pictures about arduino and avr pins.

The following is an example from the Arduino website.

DDRD is the direction register for Port D (Arduino digital pins 0-7). The bits in this register control whether the pins in PORTD are configured as inputs or outputs so, for example:    

DDRD = B11111110; // sets Arduino pins 1 to 7 as outputs, pin 0 as input
DDRD = DDRD | B11111100; // this is safer as it sets pins 2 to 7 as outputs
                         // without changing the value of pins 0 &amp; 1, which are RX &amp; TX 


See the bitwise operators reference pages and The Bitmath Tutorial in the Playground

PORTD is the register for the state of the outputs. For example;

PORTD = B10101000; // sets digital pins 7,5,3 HIGH


You will only see 5 volts on these pins however if the pins have been set as outputs either by using the DDRD register directly or by using the  pinMode() function.

For analog read

You just need to include the headers and start using the registers. They hold the equivalent hexadecimal values for your microcontroller. And the procedure is described in the datasheet. All you have to do is to translate it to code.

// this code scans ADC1 for an analog signal upon request, using 8Mhz processor clock

#include &lt;avr/io.h&gt;
#include &lt;stdint.h&gt;       // needed for uint8_t

int ADCsingleREAD(uint8_t adctouse)
{
    int ADCval;

    ADMUX = adctouse;        // use #1 ADC
    ADMUX |= (1 &lt;&lt; REFS0);   // use AVcc as the reference
    ADMUX &amp;= ~(1 &lt;&lt; ADLAR);  // clear for 10 bit resolution

    // 128 prescale for 8Mhz
    ADCSRA |= (1 &lt;&lt; ADPS2) | (1 &lt;&lt; ADPS1) | (1 &lt;&lt; ADPS0);

    ADCSRA |= (1 &lt;&lt; ADEN);    // Enable the ADC
    ADCSRA |= (1 &lt;&lt; ADSC);    // Start the ADC conversion

    while(ADCSRA &amp; (1 &lt;&lt; ADSC)); // waits for the ADC to finish

    ADCval = ADCL;
    ADCval = (ADCH &lt;&lt; 8) + ADCval; // ADCH is read so ADC can be updated again

    return ADCval;
}
   

int main(void)
{
    int ADCvalue;

    while (1)
    {
        ADCvalue = ADCsingleREAD(1);
        // ADCvalue now contains an 10bit ADC read
    }
}


For more information about analog read, see this.