0

using g++ compiler and code is compiling and running successfully. as I know that C doesn't have separate data type for string and stores the string as an array of character I don't know why the heck this is compiling without initializing the char as array.

#include <stdio.h>
int main(){

int total_ch=0;
int total_courses=2;
float sum=0.0;
float gpa=0.0;


for(int i=0;i < total_courses; i++){
    printf("%d \n",total_courses);
char course;
int marks=0;
int ch=0;
float cgpa=0.0;
printf("Enter the course name: \n");
scanf(" %s",course);
printf("Enter the credit hours of the course\n");
scanf(" %d",&ch);
printf("Enter the marks of the course\n");
scanf(" %d",&marks);
total_ch += ch;
if (marks > 85){
 printf("Your Cgpa of %s is 4.00 and your grade is A\n",&course);
 sum+=(ch*4.00);
}else if (marks > 79 && marks < 86 ){
 printf("Your Cgpa of %s is 3.67 and your grade is A-\n",&course);
 sum+=(ch*3.67);
}else if (marks > 75 && marks < 80){
 printf("Your Cgpa of %s is 3.33 and your grade is B+\n",&course);
 sum+=(ch*3.33);
}else if (marks > 71 && marks < 76){
 printf("Your Cgpa of %s is 3.00 and your grade is B\n",&course);
 sum+=(ch*3.00);
}else if (marks > 67 && marks < 72){
 printf("Your Cgpa of %s is 2.67 and your grade is B-\n",&course);
 sum+=(ch*2.67);
}else if (marks > 63 && marks < 68){
 printf("Your Cgpa of %s is 2.50 and your grade is C+\n",&course);
 sum+=(ch*2.50);
}else if (marks > 59 && marks < 64){
 printf("Your Cgpa of %s is 2.00 and your grade is C\n",&course);
 sum+=(ch*2.00);
}else if (marks > 56 && marks < 60){
 printf("Your Cgpa of %s is 1.67 and your grade is C-\n",&course);
 sum+=(ch*1.67);
}else if (marks > 53 && marks < 57){
 printf("Your Cgpa of %s is 1.33 and your grade is D+\n",&course);
 sum+=(ch*1.33);
}else if (marks > 49 && marks < 54){
 printf("Your Cgpa of %s is 1.00 and your grade is D\n",&course);
 sum+=(ch*1.00);
}else if (marks < 50){
 printf("Your Cgpa of %s is 0.00 and your grade is F\n",&course);
 sum+=(ch*0.0);
}


}
gpa=sum/total_ch;
printf("Your total GPA of this semester is %f",gpa);


}
Thomas Sablik
  • 16,127
  • 7
  • 34
  • 62
user61855
  • 15
  • 3
  • 1
    It's undefined behavior. It might work because pointer arithmetic still works, but it might also kill a kitten. – Robert Harvey Jan 01 '21 at 15:14
  • `scanf(" %s",course);` has multiple problems. Start by turning on compiler warnings (`-Wall -Wextra` for gcc and clang); it'll tell you about one of them. – Shawn Jan 01 '21 at 15:17
  • Hint: using structs and arrays the number of lines of your code can be reduced by about a factor 3 – Jabberwocky Jan 01 '21 at 15:35

3 Answers3

1

The variable declared in the program

char course;

is a variable that holds just a single character. It is not an array of char, nor a generic string (unless you are fine with 1-character string). So there is no initialized array, because there is no array.

To have a C-style string, that is, an array of char, you have to declare something like

char course[100];

This will declare an array of 100 chars, uninitialied of course.

In the program you posted, if you compile with enabled warnings, you will see immediately this:

main.cpp:17:10: warning: format '%s' expects argument of type 'char*', but argument 2 has type 'int' [-Wformat=]

   17 | scanf(" %s",course);

You have two problems here: first you should pass a pointer to char, where the string is stored. By passing course the compiler converts it to a pointer, and writes the read string who-knows-where, leading to UB.

Secondly, if you pass a pointer to char, you should make sure that it points to an allocated area of memory, long enough to store the result. E.g.:

char course[100];
scanf("%s", course);

But that has also a problem: what happens if the result of scanf exceeds the allocated size 100? Then, you will run into a buffer overflow, again UB. In fact, this is a major problem in using scanf to read a string. See this question and the accepted answer for better alternatives.

francesco
  • 7,189
  • 7
  • 22
  • 49
1

So why does the compiler allow this at all?

C is a very old language, by today's standards. Undefined Behavior is an artifact of the days when you could write a program that conformed to the quirks of a specific machine, without having to worry about the compiler complaining.

In the early versions of C, undefined behavior's primary advantage was the production of performant compilers for a wide variety of machines: a specific construct could be mapped to a machine-specific feature, and the compiler did not have to generate additional code for the runtime to adapt the side effects to match semantics imposed by the language. The program source code was written with prior knowledge of the specific compiler and of the platforms that it would support.

https://en.wikipedia.org/wiki/Undefined_behavior

The article goes on to say that

For C and C++, the compiler is allowed to give a compile-time diagnostic in these cases, but is not required to: the implementation will be considered correct whatever it does in such cases, analogous to don't-care terms in digital logic. It is the responsibility of the programmer to write code that never invokes undefined behavior, although compiler implementations are allowed to issue diagnostics when this happens.

Which is why you should always compile with warnings on.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
0

The reason why this doesn't work is because strings are stored as char pointers but you pass just a char variable to the scanf method. This doesn't result in a compile time error but a warning must have been issued. Make sure you pass in a valid char array with an adequate size to store the course name. For example: char course[100];

D-RAJ
  • 3,263
  • 2
  • 6
  • 24
  • This doesn't answer the question the OP asked. – Robert Harvey Jan 01 '21 at 15:23
  • Actually, the OP's question is why this *does* work. – Robert Harvey Jan 01 '21 at 15:31
  • 1) Strings are stored in arrays not pointers. 2) [Arrays are not pointers.](https://stackoverflow.com/questions/1641957/is-an-array-name-a-pointer) – Blastfurnace Jan 01 '21 at 15:31
  • @Blastfurnace: The very first sentence in the accepted answer of your linked post reads "...but in most cases array names are converted to pointers." – Robert Harvey Jan 01 '21 at 15:32
  • @RobertHarvey The first sentence of this answer, before the edit, stated "Strings are stored in char pointers". I know about array decay. This answer is still misleading, strings are arrays not char pointers. – Blastfurnace Jan 01 '21 at 15:33