Int Var = 1; Void Main() { Int I = I; }

Variable Declaration and Scope in C

This might help. source

Declaration of a variable is for informing to the compiler the
following information: name of the variable, type of value it holds
and the initial value if any it takes. i.e., declaration gives details
about the properties of a variable. Whereas, Definition of a variable
says where the variable gets stored. i.e., memory for the variable is
allocated during the definition of the variable.

In C language definition and declaration for a variable takes place at
the same time. i.e. there is no difference between declaration and
definition. For example, consider the following declaration

int a;

Here, the information such as the variable name: a, and data type:
int, which is sent to the compiler which will be stored in the data
structure known as symbol table. Along with this, a memory of size 2
bytes(depending upon the type of compiler) will be allocated.

Suppose, if we want to only declare variables and not to define it
i.e. we do not want to allocate memory, then the following declaration
can be used

extern int a;

In this example, only the information about the variable is sent and
no memory allocation is done. The above information tells the compiler
that the variable a is declared now while memory for it will be
defined later in the same file or in different file.

Why doesn't this give compilation error?

Actually, compiler might give you a hint. Mine says: "warning C4700: local variable 'a' used without having been initialized".

But this is not an error per se, declaration just gives a variable name to some bits of memory without touching it, which is valid and fast. And the assigment here is not really an assigment, just moving bits from right to left. No checks again. Very productive, very unsafe.

Every operation is legal, but the whole thing is pointless. So compiler does the best thing it can - it compiles the code, but gives a warning too.

Using this.var during var's initialization

It is mentioned in passing in the Example 8.3.2.3-1 in section 8.3.2.3. In the text to the example

class Z {
static int peek() { return j; }
static int i = peek();
static int j = 1;
}
class Test {
public static void main(String[] args) {
System.out.println(Z.i);
}
}

the caption says:

... the variable initializer for i uses the class method peek to access the value of the variable j before j has been initialized by its variable initializer, at which point it still has its default value (§4.12.5).

This should map directly to your situation.

translation from c to mips

You didn't mention which IDE you're using (e.g. spim, mips, etc.). So, I used mars.

In C, when you index into an array, the compiler computes the offset based on the size [in bytes] of the element (e.g. for an int, this is 4). So, if the code was:

x = C[var]

The "effective" code would be:

x = *(int *) (((char *) C) + (var * 4));

In assembler, we have to do the same thing.

Here's the code with annotations:

    .data
A: .word 2, 3, 4, 5
B: .word 1, 1, 2, 3
C: .word 0, 0, 0, 0

.text
.globl main
# s0 -- actualizacion
main:
li $s0,1 # actualizacion = 1

li $a0,4
jal updateValues

addi $s0,$s0,1 # actualizacion += 1

li $v0,10
syscall

.globl updateValues
# a0 -- var (array index)
# t0 -- var << 2 (byte offset)
# t1 -- array address
# t2 -- B value
# t3 -- C value
updateValues:
li $t0,4
bne $a0,$t0,update_default

update_loop:
addi $a0,$a0,-1 # var -= 1
sll $t0,$a0,2 # convert index into byte offset

la $t1,B # base address of B
addu $t1,$t1,$t0 # add in byte offset
lw $t2,0($t1) # load value

la $t1,C # base address of C
addu $t1,$t1,$t0 # add in byte offset
lw $t3,0($t1) # load value

sub $t2,$t2,$t3 # B - C

la $t1,A # base address of A
addu $t1,$t1,$t0 # add in byte offset
sw $t2,0($t1) # store value

bnez $a0,update_loop # loop until var == 0
b update_exit

update_default:
li $t0,2
mul $a0,$a0,$t0 # var = var * 2

update_exit:
jr $ra # return

Understanding copy-initialization in C++, compared to explicit initialization

In your first code, both declarations should compile. GCC is right there. Visual C++ Compiler has bug.

And in the second code, the inner declaration should not compile. GCC is right there too, and VC++ is wrong.

GCC is right in both cases.

A code like int a=a+100; and int a(a+100); is fine from syntax point of view. They might invoke undefined behavior depending on whether they're created in static storage duration or automatic storage duration.

int a = a + 100; //well-defined. a is initialized to 100
//a on RHS is statically initialized to 0
//then a on LHS is dynamically initialized to (0+100).
void f()
{
int b = b + 100; //undefined-behavior. b on RHS is uninitialized

int a = a + 50; //which `a` is on the RHS? previously declared one?
//No. `a` on RHS refers to the newly declared one.
//the part `int a` declares a variable, which hides
//any symbol with same name declared in outer scope,
//then `=a+50` is the initializer part.
//since a on RHS is uninitialized, it invokes UB
}

Please read the comments associated with each declaration above.

Note that variables with static storage duration is statically initialized to zero at compile time, and if they've initializer, then they're dynamically initialized also at runtime. But variables of POD types with automatic storage duration are not statically initialized.

For more detail explanation on static initialization vs dynamic initialization, see this:

  • What is dynamic initialization of object in c++?

What does this mean const int*& var?

It is a reference to a pointer to an int that is const.

There is another post somewhat related, actually, here. My answer gives a sorta of general algorithm to figuring these things out.

This: const int& *var has no meaning, because you cannot have a pointer to reference.

If the const's and pointers are getting in the way, remember you can typedef these things:

typedef int* IntPointer;
typedef const IntPointer ConstIntPointer;

void foo(ConstIntPointer&); // pass by reference
void bar(const ConstIntPointer&); // pass by const reference
void baz(ConstIntPointer); // pass by value

Might make it easier to read.


If you need more help on C++, read this. More specifically, references.

References as variables do not take space:

int i; // takes sizeof(int)
int*pi = &i; // takes sizeof(int*)

int& ri = i; // takes no space.
// any operations done to ri
// are simply done to i

References as parameters use pointers to achieve the end effect:

void foo(int& i)
{
i = 12;
}

void foo_transformed(int *i)
{
*i = 12;
}

int main()
{
int i;

foo(i); // same as:
foo_transformed(&i); // to the compiler (only sort of)
}

So it's actually passing the address of i on the stack, so takes sizeof(int*) space on the stack. But don't start thinking about references as pointers. They are not the same.



Related Topics



Leave a reply



Submit