The following code compiles fine on Linux using gcc -std=c99 but gets the following errors on the Visual Studio 2010 C compiler:
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
fib.c
fib.c(42) : error C2057: expected constant expression
fib.c(42) : error C2466: cannot allocate an array of constant size 0
fib.c(42) : error C2133: 'num' : unknown size
The user inputs the amount of Fibonacci numbers to generate. I'm curious as to why the Microsoft compiler doesn't like this code.
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
void fib(int max);
int main(int argc, char *argv[])
{
int argument;
if (argc != 2)
{
puts("You must supply exactly one command line argument.");
return 0;
}
argument = atoi(argv[1]);
if (argument == 0)
{
puts("You gave us 0 or an invalid integer.");
return 0;
}
else if (argument < 0)
{
puts("You gave us a negative integer.");
return 0;
}
else if (argument == INT_MAX)
{
puts("You gave us a number that's too big to fit in an integer.");
return 0;
}
printf("%d\n", argument);
fib(argument);
return 0;
}
void fib(int max)
{
int num[max]; /// <- Line 42
int i;
for (i = 0; i < max; i++)
{
if (i == 0)
num[i] = 0;
else if (i == 1)
num[i] = 1;
else
num[i] = num[i-1] + num[i-2];
printf("%d\t%d\n", i, num[i]);
}
}
void fib(int max)
{
int num[max];
Microsoft's C compiler doesn't support C99, and I believe they've said it never will. That means that arrays can only be declared with constant size.
The Problem lies in the fib function.
The line "int num[max];" is the problem. This is because, compiler tries to allocate space of max number of integers, but the token max is not defined properly to the compiler at the compilation time.
You can use the dynamic memory allocation to resolve this issue.
But i wonder why you might need such huge space (when max large) as you need only previous numbers to generate the sequence.
void fib(int max)
{
int a = 0, b = 1; // first 2 numbers of the sequence.
int c, i;
for (i = 0; i < max; i++)
{
if (i == 0)
printf ("%d %d",i,a);
else if (i == 1)
printf ("%d %d",i,b);
else{
c = a+b;
printf ("%d %d",i,c);
a = b;
b = c;
}
}
}
You can change your function to dynamically allocate the array and then release the memory when finished. The rest of your function will work without change.
void fib(int max)
{
int *num = malloc(max * sizeof(int));
int i;
for (i = 0; i < max; i++)
{
/* Your code here */
}
free(num);
}
Related
I am mindblown by this small code:
#include <stdio.h>
int main()
{
int limit = 0;
scanf("%d", &limit);
int y[limit];
for (int i = 0; i<limit; i++ ) {
y[i] = i;
}
for (int i = 0; i < limit; i++) {
printf("%d ", y[i]);
}
return 0;
}
How on earth this program is not segment-faulting as limit (size of the array) is assigned at runtime only?
Anything recently changed in C? This code shouldn't work in my understanding.
int y[limit]; is a Variable Length Array (or VLA for short) and was added in C99. If supported, it allocates the array on the stack (on systems having a stack). It's similar to using the machine- and compiler-dependent alloca function (which is called _alloca in MSVC):
Example:
#include <alloca.h>
#include <stdio.h>
int main()
{
int limit = 0;
if(scanf("%d", &limit) != 1 || limit < 1) return 1;
int* y = alloca(limit * sizeof *y); // instead of a VLA
for (int i = 0; i<limit; i++ ) {
y[i] = i;
}
for (int i = 0; i < limit; i++) {
printf("%d ", y[i]);
}
} // the memory allocated by alloca is here free'd automatically
Note that VLA:s are optional since C11, so not all C compilers support it. MSVC for example does not.
This doesnt compile in visual studio because limit "Error C2131 expression did not evaluate to a constant"
If you make limit a constexpr though then the compiler will not mind because youre telling it it wont change. You cant use 0 though as setting an array to a constant size length zero is nonsence.
What compiler does this run on for you ?
I'm trying to create an array of integers of an unknown size.
Every time I input a positive element I use realloc to increase the size of the array and store that element
The thing is that when I run this code, I get a run-time error after 2 iterations of the while of the function create1DArray, so it's probably due to a realloc failure.
Can anybody tell me what I did wrong and how to fix it?
Thanks in advance,
#include <stdio.h>
#include <stdlib.h>
void create1DArray(int** perArray, int* size);
int main()
{
int *perArray, size=0, i;
create1DArray(&perArray, &size );
for(i=0; i<size; i++)
printf("%d ",perArray[i]);
free(perArray);
return 0;
}
void create1DArray(int** perArray, int* size)
{
int flag=0, i=0, x;
*perArray=(int*)malloc(sizeof(int) );
if(*perArray==NULL)
{
printf("Allocation failed!");
exit(1);
}
while(!flag)
{
if( scanf("%d", &x)<1 || (x<0) )
{
printf("Invalid input!");
free(perArray);
exit(1);
}
if(!x)
{
if( !(*size) )
{
printf("The first element of the array must not be 0");
free(perArray);
exit(1);
}
flag++;
}
else
{
*perArray=(int*)realloc(*perArray, (++(*size))*sizeof(int) );
if(*perArray==NULL)
{
printf("Reallocation failed!");
free(perArray);
exit(1);
}
*perArray[i++]=x;
}
}
}
I think I see two problems (and M Oehm spotted one more):
1) Your handling of size is wrong (or at least strange). Normally you'll do something like:
*perArray=(int*)malloc(sizeof(int) );
*size = 1;
Perhaps even better - you should drop the malloc and just initialize the pointer in main to NULL. realloc works like malloc when called with NULL.
This would also allow you to call the function several times - something you current code doesn't allow.
2) There is a problem with your realloc
*perArray=(int*)realloc(perArray, (++(*size))*sizeof(int) );
^^^^
Should be *perArray
3) You need to dereference the pointer before indexing (noticed by M Oehm - thanks).
*perArray[i++]=x; ---> (*perArray)[i++]=x;
May not be exactly what you want, but take a look at how it can be done concisely (although doing realloc at each iteration is inefficient). It should be compiled with the flag std=c11.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main()
{
int size = 0;
int input = 0;
int * perArray = NULL;
while(scanf("%d", &input) && input > 0)
{
++size;
perArray = (int *) realloc(perArray, sizeof(int) * (long unsigned) size);
assert(perArray);
perArray[size - 1] = input;
}
if(perArray)
{
for(int i = 0; i < size; ++i) printf("%d ", perArray[i]);
printf("\n");
free(perArray);
}
return 0;
}
I have recently started coding in C, and am doing some stuff on project Euler. This is my code for challenge three so far. The only problem is when I run the compiled code it throws a segmentation fault. I think it may be due to a pointer I called, the suspect pointer is underneath my comment. I did some research into the subject but I cant seem to be able to fix the error. Any advice?
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
bool is_prime(int k);
int * factors(int num);
int main(){
int input;
while (true){
printf("Enter a number to get the prime factorization of: ");
scanf("%d", &input);
if (is_prime(input) == true){
printf("That number is already prime!");
}else{
break;
}
}
//This is the pointer I think is causing the problem
int * var = factors(input);
int k;
for (k = 0; k < 12; k++){
printf("%d", var[k]);
}
}
bool is_prime(int k){
int i;
double half = ceil(k / 2);
for (i = 2; i <= half; i++){
if (((int)(k) % i) == 0){
return false;
break;
}
}
return true;
}
int * factors(int num){
int xi;
static int array[1000];
int increment = 0;
for (xi = 1;xi < ceil(num / 2); xi++){
if (num % xi == 0){
array[increment] = xi;
increment++;
}
}
}
The factors function has no return statement. It's supposed to return a pointer but it doesn't return anything.
Side note: Enable your compiler's warnings (e.g., with gcc -Wall -Wextra). If they're already enabled don't ignore them!
Your function is declared as
int * factors(int num);
but it's definition doesn't return anything and yet you are using it's return value in assignment. This triggers undefined behavior. It will compile if compiled without rigorous warnings and the return value will most likely be whatever random value happened to be left in the return register (e.g. EAX on x86).
C-99 Standard ยง 6.9.1/12 Function definitions
If the } that terminates a function is reached, and the value of the
function call is used by the caller, the behavior is undefined.
I'm trying to solve this problem https://www.hackerrank.com/challenges/flowers
When I run my code in Visual Studio 2013 on Windows 7 on my machine I get the correct answers but on the site (I'm pretty sure they use Linux and I'm positive this is the compiler they use gcc 4.9.2, C99 standard) I get very large numbers for answers, specifically 12588576 (instead of 13) for the first test case and 1395920336 (instead of 15) for the second test case. I'm guessing it has something to do with the qsort call.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int comp_desc(const void * a, const void * b)
{
int * aPtr = (int*)a;
int * bPtr = (int*)b;
return *bPtr - *aPtr;
}
int main()
{
int flowersNeeded, numFriends, i;
scanf("%d %d", &flowersNeeded, &numFriends);
getchar();
int flowerCosts[100];
memset(flowerCosts, 0, 100);
for (i = 0; i < flowersNeeded; ++i)
{
scanf("%d", &flowerCosts[i]);
}
qsort(flowerCosts, 100, sizeof(int), comp_desc);
int flowersBought = 0;
int moneySpent = 0;
int multiplier = 1;
for (i = 0; i < flowersNeeded; ++i)
{
moneySpent += flowerCosts[i] * multiplier;
multiplier = (++flowersBought / numFriends) + 1;
}
printf("%d\n", moneySpent);
return 0;
}
memset(flowerCosts, 0, 100);
The 100 should be sizeof(flowerCosts). The 100 doesn't fill the whole array because it's the size in bytes.
qsort(flowerCosts, 100, sizeof(int), comp_desc);
You probably want to sort only the entries you filled in (flowersNeeded) rather than all 100 of them.
As a result of these two bugs, you're sorting garbage values in the uninitialized part of your array.
I'm trying to learn C by writing a simple program to output Fibonacci numbers. It isn't working.
fibonacci.h
unsigned int fibonacci_recursive(unsigned int n);
fibonacci.c
#include <stdio.h>
#include "fibonacci.h"
main() {
unsigned int i;
for (i = 0; i < 10; i++) {
printf("%d\t%n", fibonacci_recursive(i));
}
getchar();
}
fibonacci_recursive.c
unsigned int fib_rec(unsigned int n);
main(unsigned int n) {
return fib_rec(n);
}
unsigned int fib_rec(unsigned int n) {
if (n == 0) {
return 0;
}
if (n == 1) {
return 1;
}
return fib_rec(n - 1) + fib_rec(n - 2);
}
This is the error message VS 2010 gives me when I try to build the project:
1>ClCompile:
1> fibonacci_recursive.c
1>fibonacci_recursive.obj : error LNK2005: _main already defined in fibonacci.obj
1>fibonacci.obj : error LNK2019: unresolved external symbol _fibonacci_recursive referenced in function _main
1>c:\users\odp\documents\visual studio 2010\Projects\Fibonacci\Debug\Fibonacci.exe : fatal error LNK1120: 1 unresolved externals
1>
1>Build FAILED.
1>
What am I doing wrong here? Thanks for helping someone new to C.
Your approach seems strange, you should have:
a main file (example main.c) with the main method and that includes fibonacci.h
a fibonacci.h with the prototype unsigned int fibonacci_recursive(unsigned int n);
a fibonacci.c with the implementation of the method, and it should include fibonacci.h too
Actually you define main function twice too..
main.c
#include <stdio.h>
#include "fibonacci.h"
main()
{
unsigned int i;
for (i = 0; i < 10; i++)
{
printf("%d\t%n", fibonacci_recursive(i));
}
getchar();
}
fibonacci.h
unsigned int fibonacci_recursive(unsigned int n);
fibonacci.c
#include "fibonacci.h"
unsigned int fibonacci_recursive(unsigned int n)
{
if (n == 0)
{
return 0;
}
if (n == 1) {
return 1;
}
return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2);
}
You have the main() function defined twice in your project. This is the entry point of your program, and you only need one.
You need \n not %n for your printf. Also, you can simplify as:
#include "fibonacci.h"
unsigned int fibonacci_recursive(unsigned int n) {
if (n < 2)
return n;
else
return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2);
}
You haven't created a fibonacci_recursive function that you declared in fibonacci.h.
You declared two main() functions, and the new line character is '\n'.
Well, I preface that recursive function is not an efficient method to calculate Fibonacci and it may be used for dev training/demonstrations purposes only, because every recursion is stored in stack, and it may also overflow for large fibonacci numbers.
It is rather worth the effort to write down a more efficient Fibonacci function that uses a loop, like following code:
#include <stdio.h>
#define MAX_ITERS 20
int fibonacci(int);
int main(int argc, char *argv[])
{
unsigned int iters;
if(argc>1) {
iters=atoi(argv[1]);
} else
iters=MAX_ITERS;
fibonacci(iters);
return 0;
}
int fibonacci(int iterations)
{
unsigned register int i;
double first=0.0, second = 1.0, lastsum;
printf("First %d iterations of Fibonacci series are :\n",iterations);
for ( i = 0 ; i < iterations ; i++ )
{
if ( i <= 1 )
lastsum = (double)i;
else
{
lastsum = first + second;
first = second;
second = lastsum;
}
printf("%.0f\n",lastsum);
}
}
Try to compare by your own, running ./fibonacci 50 with this method, for instance on a low cost processor (eg. on a Raspberry PI), and the one with the recursive functions and 50 first numbers as well, and see the difference! ,-)