2010-12-13 1 views
9

Допустим, у меня есть следующий фрагмент кода:функция пау C отказывается работать с переменным показателем

int i; double value; 
for(i = 0; i < CONSTANT; i++) { 
    value = (double)pow(2, i); 
} 

Попытка скомпилировать этот код дает «неопределенная ссылка на` '»ошибка ПР.

Включая или исключая math.h, не имеет значения, так как он в конечном итоге включен.

Подъем 2.0 для жестко закодированного питания работает нормально, но все не удается, если подставить экспоненту выражение, содержащее i.

Что я делаю неправильно? Благодарю.

+0

Какой компилятор вы используете? Есть ли другое возможное объявление 'pow()'? Не могли бы вы процитировать ошибку? –

+0

Я использую GCC и нет другого объявления 'pow'. На вопрос однозначно ответил; почти все ответы помогли мне. Хотел бы я принять более одного. :) Всем спасибо. – 2010-12-13 16:52:57

+5

Пока другие комментируют, почему 'pow' не работает, весь факт, что вы используете' pow', представляет собой огромную проблему с вашим кодом. ** C имеет оператор для базы экспонентов 2 **, и это называется '<<'. Удалите это бесполезное использование 'pow' и замените его на' 1 << i', и забудьте о 'double'. –

ответ

16

Это очень интересное поведение, и хороший пример обучения.

Чтобы решить вашу проблему, добавьте

-lm 

в командной строке НКУ (при условии, что вы используете GCC). Это говорит компилятору о связи с математической библиотекой.

Что, кажется, происходит, является то, что если вы используете

pow(2.0, 3); 

компилятор понимает это выражение постоянной, и делает лишь замену.

Таким образом, библиотечная функция не должна вызываться.

+0

Это объяснение, о котором я собирался опубликовать. Компилятор также может оптимизировать 'pow (n, 2)' to 'n * n' или аналогичный. – zwol

+1

Собственно, в качестве последующего комментария .. компиляция этого цикла в одиночку, с максимальной оптимизацией (-O3) фактически работает без -lm. Это связано с тем, что значение больше не используется, и компилятор просто разворачивает и оптимизирует бесполезный цикл и бесполезную функцию pow(), поэтому никогда не нужно вызывать функцию pow() из библиотеки libm. – qdot

3

Вам нужно связать с -lm, чтобы фактически включить математическую библиотеку.

Он работал с жестко запрограммированным значением, потому что компилятор оптимизировал вызов pow.

0

http://www.cplusplus.com/reference/clibrary/cmath/pow/

В C, только версия с двух двойных параметров существует с этим именем. Другие перегрузки доступны только на C++.

Похоже, вы не можете передать int, так что просто сделайте i двойным, и это должно сработать.

+0

«Обычные арифметические преобразования» преобразуют int в double при необходимости. Вы лаяете неправильное дерево. – zwol

+0

И что заслуживает отметки? Jeez. – acron

+0

Это неправильный ответ, и он отвечает на неправильный вопрос. Так что да. – zwol

1

Код для pow является частью математической библиотеки. Вам нужно связать в этой библиотеке (в дополнение к библиотеке C, которая по умолчанию связана).

Чтобы сделать это, с НКОЙ, указать -lm на компилятор вызов

gcc ... -lm 
+3

Незначительное оговорка: переключатели '-l' всегда должны быть помещены * после * всех объектных файлов в командной строке. Случается, что вы работаете над некоторыми дистрибутивами Linux, если вы этого не сделаете, но на это нельзя положиться. – zwol

3

Вы должны связать с библиотекой математики:

gcc program.c -lm 

Причина заключается в том, что GCC (и некоторые другие компиляторы) имеют встроенные функции для pow() литералов. Поэтому, если вы вызываете pow() с 2.0 вручную, компилятор фактически выяснит, что ответ, и замените это для вас. При переменном вводе компилятор должен полагаться на математическую библиотеку, с которой вы должны ссылаться.