Navigation

Sunday 28 October 2018

Why does C scanf only accept char a[n]?

#include <stdio.h>
int main(void)
{
    char *name;
    scanf("%s", name);
    printf("You've entered %s\n", name);

    return 0;
}
Look at the above code.
The book says it may or may not be compiled.
It can be compiled on my Linux. But it runs and I type hello, it is not right.
hello
You've entered (null)
I know name is an uninitialized pointer why may point to anything.
So the proper way to correct this is char name[81];
Now I made some change.
I initialize name at the very beginning, like this:
#include <stdio.h>
int main(void)
{
    char *name = "aaa";
    scanf("%s", name);
    printf("You've entered %s\n", name);

    return 0;
}
It can also be compiled. But when I type hello, I get this:
[Tom@localhost ~]$ ./a.out 
hello 
Segmentation fault (core dumped)
Now that name has been initialized which in my understanding should be given an specific address.
Why it still fails to work ?


Here

Sunday 21 October 2018

Can you give an example of prvalue in C language?

Why can't pointer to float be assigned to another pointer to float in C language?

#include <stdio.h>
void print(float *p, int n); 
int main(void)
{
    float rootbeer[10];
    float things[10][5];

    things[5] = rootbeer;
    return 0;
}
Look at the above C code snippet.
rootbeer is pointer to a floating number.
things[5] is the same as things[5] + 0, which is also pointer to a floating number.
So in my view, rootbeer can be assigned to things[5].
I anticipated it should be able to be compiled successfully.
However, after gcc -std=c11 test.c
I got the error message as below:
test.c: In function ‘main’:
test.c:9:12: error: incompatible types when assigning to type ‘float[5]’ from type ‘float *’
  things[5] = rootbeer;
Why can't pointer to float be assigned to another pointer to float ?


https://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues

Is a the same as &a in scanf in C language ?

#include <stdio.h>
int main(void)
{
    float rootbeer[10];

    scanf("%f", rootbeer);

    printf("%f\n", *rootbeer);

    return 0;
}
Look at the above code.
It works well.
In my understanding, rootbeer is the same as rootbeer + 0, which is pointer to a floating number.
Now I change rootbeer in scanf to &rootbeer.
#include <stdio.h>
int main(void)
{
    float rootbeer[10];

    scanf("%f", &rootbeer);

    printf("%f\n", *rootbeer);

    return 0;
}
I anticipated an error message because I think &rootbeer is pointer to array of 10 of float.
However, the changed code can also be compiled and works perfectly.
I wonder why.
Is a the same as &a in scanf in C language ?

Here

gcc -std=c11 -Wall -Werror ***.c   should be able to show all errors, including those undefined behaviour that still can be compiled.

Wednesday 17 October 2018

Is a[i] really the same as *(a + i) in C ?

#include <stdio.h>
int sum2d(int row, int col, int p[row][col]);
int main(void)
{
    int a[2][3] = {{1, 2, 3}, {4, 5, 6}};

    printf("%d\n", sum2d(2, 3, a));


    return 0;
}
int sum2d(int row, int col, int p[row][col])
{
    int total = 0;
    for (int i = 0; i < row; i++)
        for (int j = 0; j < col; j++)
            total += (*(p + i))[j];
    return total;
}
Look at the above code. It works perfectly.
However, after I changed p[row] into *(p + row),
#include <stdio.h>
int sum2d(int row, int col, int (*(p + row))[col]);
int main(void)
{
    int a[2][3] = {{1, 2, 3}, {4, 5, 6}};

    printf("%d\n", sum2d(2, 3, a));


    return 0;
}
int sum2d(int row, int col, int (*(p + row))[col])
{
    int total = 0;
    for (int i = 0; i < row; i++)
        for (int j = 0; j < col; j++)
            total += (*(p + i))[j];
    return total;
}
it can't be compiled and displays the following error message :
test.c:2:38: error: expected ‘)’ before ‘+’ token
 int sum2d(int row, int col, int (*(p + row))[col]);
                                      ^
test.c: In function ‘main’:
test.c:7:2: warning: implicit declaration of function ‘sum2d’ [-Wimplicit-function-declaration]
  printf("%d\n", sum2d(2, 3, a));
  ^
test.c: At top level:
test.c:12:38: error: expected ‘)’ before ‘+’ token
 int sum2d(int row, int col, int (*(p + row))[col])
At my current level, I barely understand it.
In C, I thought a[i] = *(a + i) .
Why is my code not correct ?

Here

Monday 15 October 2018

ⓩ - Why do we use double instead of int in C++ for the calculation of large numbers?


An ‘int’ is (typically) a 32 bit number - if you use it as an “unsigned” number - then the largest value you can store is about 4 billion.
A ‘float’ is also 32 bit number but it uses an approximation to represent numbers. It’s basically a number between 0 and 1 (called the ‘mantissa’) - multiplied by 2 to the power some other number (called the ‘exponent’). So packed into those 32 bits are TWO numbers rather than one. Hence the accuracy (which is determined by the mantissa) isn’t as good as an integer - but the SIZE of the number (which is determined by the exponent) can be much MUCH larger.
The largest number you can store in a ‘float’ is roughly 1038 - which is more atoms than there are in every human being on Earth…a pretty decent size for most purposes. But the bigger the number gets - the less accurately it’s stored. So for precision work - we tend to use integers.
A ‘double’ is a 64 bit number - and it works the same way as a ‘float’ - but has more space for the mantissa and exponent. 52 bits of mantissa, 11 bits of exponent and a sign bit (plus/minus). The largest ‘double’ is around 10384 - which is an ungodly large number - VASTLY bigger than the number of atoms in the visible universe (about 1082).
But to be VERY clear - floats and doubles are APPROXIMATE representations. integers are EXACT.

Of course if you’re willing to consume 64 bits to store a double - you could have used a ‘long int’ - which is (probably) 64 bits - and can store whole numbers up to about 1019 with perfect precision.

Source:Why do we use double instead of int in C++ for the calculation of large numbers?

Sunday 14 October 2018

Can const data type replace #define in C programming ?

I hear people say that const can replace #define and has more edges.
#include <stdio.h>
#define ROW 3
#define COL 4 
int sum2d(int r, int c, int (*a)[c]);
int main(void)
{
    const int row = 3;
    const int col = 4;
    int junk[row][col] = {{2, 4, 6, 8}, {3, 5, 7, 9}, {12, 10, 8, 6}};
    printf("Sum = %d\n", sum2d(row, col, junk));

    return 0;
}
int sum2d(int r, int c, int (*a)[c])
{
    int total = 0;
    for (int i = 0; i < r; i++)
        for (int j = 0; j < c; j++)
            total += a[i][j];
    return total;
}
Look at the above code which fails to be compiled.
Error message which I fail to understand:
test.c:9:2: warning: excess elements in array initializer [enabled by default]
test.c:9:2: warning: (near initialization for junk[0]’) [enabled by default]
test.c:9:2: warning: excess elements in array initializer [enabled by default]
test.c:9:2: warning: (near initialization for junk[0]’) [enabled by default]
test.c:9:2: warning: excess elements in array initializer [enabled by default]
test.c:9:2: warning: (near initialization for junk[0]’) [enabled by default]
test.c:9:2: warning: excess elements in array initializer [enabled by default]
I thought it would work but it didn't.
#include <stdio.h>
#define ROW 3
#define COL 4 
int sum2d(int r, int c, int (*a)[c]);
int main(void)
{
    const int row = 3;
    const int col = 4;
    int junk[ROW][COL] = {{2, 4, 6, 8}, {3, 5, 7, 9}, {12, 10, 8, 6}};
    printf("Sum = %d\n", sum2d(row, col, junk));

    return 0;
}
int sum2d(int r, int c, int (*a)[c])
{
    int total = 0;
    for (int i = 0; i < r; i++)
        for (int j = 0; j < c; j++)
            total += a[i][j];
    return total;
}
After changing junk[row][col] to junk[ROW][COL], it can be successfully compiled and work.
Why const int fails to work in this example?
Can't const data type  replace #define  in C programming?

Here