I am working on a compiler project using lex and yacc, and have declared a global "localVarCount" initialized to zero. when this function is called by the generated yacc code, and localVarCount is assigned to in any way, it throws the "Illegal instruction: 4" error during runtime. The offending line is shown below. I do similar incrementing and assignment to that variable in other functions with no problems.
void insertArrayScopedName(char * name, int arraySize) {
int VarCount = localVarCount;
enterName(localTable, name);
if(arraySize < 1) {
writeIndicator(getCurrentColumnNum());
writeMessage("Cannot declare an array with a size smaller than 1");
errorFlag1++;
}
for (int i = 0; i < arraySize; i++){
setCurrentAttr(localTable, (void *) VarCount);
VarCount++;
}
localVarCount = VarCount; //Offending line
return;
}
Related
When using a with one variable, we declare it to 0 as i=0 like here
but when we use two variables as if I add n = strlen to make the code more efficient then i=0 is not declared but a comma is used and n=strlen(s) is declared. Why can't we use 'i=0;' here as done in the previous code?
Edit: The cs50.h is part of the sandbox cs50 which is made by harvard.
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Input: ");
printf("Output: ");
for (int i = 0; i < strlen(s); i++)
{
printf("%c\n", s[i]);
}
}
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Input: ");
printf("Output:\n");
for (int i = 0, n = strlen(s); i < n; i++)
{
printf("%c\n", s[i]);
}
}
From C standard ISO/IEC 9899:TC3 / ISO/IEC 9899/C11, the grammar description of the for statement, §(6.8.5) iteration-statement, have 2 different forms:
for ( expression_opt ; expression_opt ; expression_opt ) statement
for (declaration expression_opt ; expression_opt ) statement
Note that in the first form we have an expression in the first position, although it is optional as all 3 fields, and all the 3 parts of the statement form are separated by a ; semicolon used as a delimiter.
In the second form we can see that the first element in parenthesis is a declaration instead of an expression, and we can note also that there is no semicolon delimiting it. This is because the declaration itself is always terminated by a semicolon.
Paragraph (6.7) declaration describe grammar for a declaration:
declaration-specifiers init-declarator-list_opt ;
As you can see a declaration is always terminated by a semicolon.
A declaration can assume of course the form of multiple declarations initialized as in your:
for (int i = 0, n = strlen(s); i < n; i++)
{
printf("%c\n", s[i]);
}
So you are using the second form where the semicolon delimits the declaration (not the first part of the for).
Using multiple semicolon is simply a grammar error.
Not sure if I understand the question (although I like it). Both your code snippets work, don't they? Note that we don't know what is in cs50.h, but I tried compiling this, and it worked (both compiling and running).
#include <stdio.h>
#include <string.h>
int main(void) {
char *s = "Hello world!";
printf("Output:\n");
for (int i = 0, n = strlen(s); i < n; i++) {
printf("%c\n", s[i]);
}
}
Two things might be relevant here;
- how for works and
- how variable declaration/initialization works.
You can think about for like this:
for(AAA; BBB; CCC) DDD;
is the same as
{ // Important!
AAA;
while(BBB) {
{
DDD;
}
CCC;
}
} // Important!
The // Important! braces are important because the for introduces a new scope, i.e. i and n won't accessible outside/after the for loop.
The other thing is declaration/initialization. So the
int i = 0, n = strlen(s);
is an initialization of two variables: i, n. I'm not 100% sure about the proper vocabulary and rules (you can consult the standard), but the idea is that a declaration looks like:
TYPE VAR1, VAR2, ..., VARn
where the VARx is a variable name declared, or an "assignment" in which case it is an initialization.
UPDATE/PART2:
Usually how I would do this is something like:
const int len = strlen(s);
// Good practice to declare const what every you know wont change
for(int i = 0; i < len; i++) {
// whatever
}
But, what if the confusing coma/semicolon could be made consistent and since the semicolon is a must let's try to make everything a semicolon, I've tried this:
for ({int i = 0; int n = strlen(s); }; i < n; i++) {
// what ever
}
This did not compile, but it also didn't make sense, since if this would have "worked" (in the sense I thought I could but actually couldn't), i and n would be declared in the small block and it wouldn't be accessible anywhere else, i.e. in i < n would not be accessible. So to make them accessible we could try this:
int i, n;
for ({i = 0; n = strlen(s); }; i < n; i++) {
printf("%c\n", s[i]);
}
Now this should have worked if the for-while equivalency stated above would be 100% true, but it's not since apparently the the AAA has to be a single statement (usually a declaration) and it can't be a block i.e. {...}. Exact compiler error:
cc hola.c -o hola
hola.c: In function ‘main’:
hola.c:8:8: error: expected expression before ‘{’ token
8 | for ({
| ^
make: *** [<builtin>: hola] Error 1
but as you can see it is already very ugly and all... so yes, you need to use , to separate the declarations/initializations and a ; to terminate it.
I'm trying to convert character of a string to uppercase letters
int main (void)
{
int i = 0;
int n = 0;
static char *str[] = { "wow",
"RACEcar",
"No devil lived on.",
"rotor" };
for(i = 0; i < strlen(*str); i++)
{
if(str[i] != NULL)
{
n = function(str[i]);
}
}
return 0;
}
int function(char* x)
{
int i = 0;
int j = strlen(x);
char c;
for(i = 0; i < j; i++)
{
c = toupper(x[i]);
x[i] = c;
}
return 0;
}
I got an error saying exc bad access, code 2 at line where x[i] = c;
I'm not sure why I get this error, do I need to create another string and assign c to the new string?
toupper return the uppercase version of the character but didnt actually change the element itself, so I'm not sure what wrong with assigning the value return by toupper back to the element.
Your code attempts to modify a string literal , which causes undefined behaviour.
The string "No devil lived on." is non-modifiable. To help the compiler catch the error you should declare the array as:
static char const *str[] = { "wow", // etc.
For historical reasons, the compiler has to let it pass without breaking compilation if you forget to include the const. But it is still an error nonetheless, and some compilers will warn anyway.
For gcc you can use the flag -Wwrite-strings to disable support for the historical case; this will cause an error message to be generated for your code as-is.
I'm having an issue with printing out my struct array. It is initialized like so:
struct matrix tokens[nbrState][12];
I then try to print it out with this code:
printf("%d", tokens[0][0].state);
for(int q = 0; q < nbrState; q++){
for(int r = 0; r < 12; r++){
printf("%d", tokens[q][r].state);
}
}
How ever it just gives back
160833216083325909500442637211181530452359314445659095247095039827295039732859091035295039760059091066417471141950397584105931452485931525045870278695909110245869685280135590599950397784950397744593145248159314402459314316859095284905931452481590950044135934508013593144456590952470095039760058696836095039787258698266456147669503978565869965120593144552593143168419536358702168841950960596593143168950398056950398016593144552159315536059315450459095284905931445521015931545041048576587404166341899271605931553609503978729503978563593450804195363-1141298268758698266459314316800419611295039881600950398592587297673016950398176950397984091005908849605884315520000050-100950398592419
And I'm not sure why. I'm also filling the array with values using this for loop.
while ( fscanf ( fp, "%d/%d%c", &index, &separateInt, &separateChar) == 3) {
for(int i = 0; i < 12; i++){
tokens[index][i].state = separateInt;
}
}
You said
It is initialized like so
struct matrix tokens[nbrState][12];
But the above declaration does not initialize anything (unless your array is declared with static storage duration). A local array declared in this fashion will contain garbage at the beginning. That's apparently what you are printing.
If you want your array initialized, you have to initialize it yourself. For example, this declaration
struct matrix tokens[nbrState][12] = { 0 };
will initialize everything with zeros, assuming nbrState is a constant.
If nbrState is not a constant, then you will not be able to use a = { ... } initializer in the declaration. You will have to assign the initial values to your array elements manually, using a cycle or in some other way.
Simple Question. Imagine this in ANSI-C:
int i;
for(i=0 ; i<5 ; i++){
//Something...
}
printf("i is %d\n", i);
Will this output "i is 5" ?
Is i preserved or is the value of i undefined after the loop?
Yes. If i is declared outside of the for loop it remains in scope after the loop exits. It retains whatever value it had at the point the loop exited.
If you declatred I in the loop:
for (int i = 0 ; i < 5 ; i++)
{
}
Then i is undefined after the loop exit.
Variable i is defined outside of the scope of the loop (which is great, or you wouldn't be able to print it in that case).
And it is post-icnremented for every-turn of the loop, for which the end condition is "stop when i is bigger or equal to 5".
So it really makes perfect sense for i to be equal to 5 at this point.
A block scope is not exactly the same as a function scope in C. The variable i doesn't "get back" magically to its previous value when you step out of the loop's scope.
i's value will be 5 after your loop. Unless you did something like
i = 50000;
inside of it.
It's also generally recommended against using "i" after you exit the loop in most coding standards I have ever read. In particular do NOT do:
for(i = 0; i < num_elements; i++)
{
if(element[i].id == id)
{
/* Do something to element here. */
break;
}
}
if(i == num_elements)
{
fprintf(stderr, "Failed to find element %d.", id);
succeeded == false;
}
While this will work it is poor coding. It is less readable and maintainable than the alternatives. E.g.
succeeded = false;
for(i = 0; i < num_elements; i++)
{
if(element[i].id == id)
{
/* Do something to element here. */
succeeded = true;
break;
}
}
if(false == succeeded)
{
fprintf(stderr, "Failed to find element %d.", id);
}
Yes, variables are valid only inside the block in which they are declared.
Here's an example:
#include <stdio.h>
void main(int argc, char *argv[])
{
if(argc == 2) {
int x;
x = 7;
}
x = 1;
}
That's the compiler:
gcc ex.c
ex.c: In function ‘main’:
ex.c:10: error: ‘x’ undeclared (first use in this function)
ex.c:10: error: (Each undeclared identifier is reported only once
ex.c:10: error: for each function it appears in.)
typedef struct _set{
int root;
int rank;
}Set;
void Kruskal(Graph* g)
{
Set uni[g->nv];
Edge result[g->nv - 1];
int i;
int count = 0;
int num = 0;
int aRoot, bRoot;
for(i = 0; i < g->nv; i++){
uni[i].root = i;
uni[i].rank = 0;
}
QuickSort(g, 0, g->ne-1);
while(count != (g->nv-1) && num != g->ne){
WeightedUnion(uni, g->path[num].src, g->path[num].dest);
aRoot = Find(uni, g->path[num].src);
bRoot = Find(uni, g->path[num].dest);
if( aRoot != bRoot){
result[num] = g->path[num];
count++;
}
num++;
}
if(count != g->nv-1){
printf("No spanning tree\n");
}
else{
for(i = 0; i <= count; i++){
printf("[%d] %d - %d : %d\n",i+1,result[i].src,result[i].dest,result[i].weight);
}
}
}
This is my part of code. The problem is that I can't initialize 'uni[g->nv]'. You can see 'for' loop next to the variable area. And I was sure about that reputation must initialize this array but a result was not. That array didn't include any other values. just empty. I cannot find my problem. Please tell me my problem or mistakes.
I run my code in Xcode. Maybe this information is helpful
You are using a variable length array (VLA), that is an array with a length that depends dynamically on an expression during run time. Since the size is not known at compile time, you can't initialize them with an initializer expression, but must do it with a for loop as you are doing.
VLA are usually realized when your program executes on the so-called stack of the function in which it is defined. That stack has a size limit and you have to be careful that you don't overrun it. (And if you do, there is no tool to know directly.)
So don't use VLA as you do for big data of unknown size. Instead, use a pointer and malloc to allocate the memory that you need.