检查是否用C预处理器声明了函数?

时间:2009-11-17 14:24:37

标签: c macros c-preprocessor

是否可以告诉 C 预处理器检查是否声明了函数(不是宏)?我尝试了以下方法,但它似乎不起作用:

#include <stdio.h>

int main(void)
{
#if defined(printf)
    printf("You support printf!\n");
#else
    puts("Either you don't support printf, or this test doesn't work.");
#endif
    return 0;
}

5 个答案:

答案 0 :(得分:22)

没有。预处理器在C编译器和C编译器处理函数声明之前运行。预处理器仅用于文本处理。

但是,大多数头文件都包含保护宏,如_STDIO_H_,您可以在预处理器阶段进行测试。但是,该解决方案不可移植,因为包含保护宏名称未标准化。

答案 1 :(得分:5)

如果你看一下像autoconf这样的工具,你会看到他们经过多次测试来确定计算机有没有,要正确编译,然后设置正确的#DEFINES。

你可能想要查看那个模型,如果你使用的是unix的那个工具,那么你想做的事情是不可能的,正如其他人无疑指出的那样。

答案 2 :(得分:1)

预处理器是一个简单的程序,几乎不知道底层语言。它无法判断是否已声明某个函数。即使可以,也可以在另一个库中定义该函数,并在链接期间解析符号,因此预处理器在这方面无法提供帮助。

答案 3 :(得分:1)

严格来说不是,预处理器不能单独完成。但是,您可以通过自动创建适当的#defines来帮助它。

通常如上所述,如果在unix类型系统上,您将使用autotools。但是,您也可以使用makefile创建相同的效果。我最近有理由发现&#34; posix_fallocate&#34;函数在头文件中定义,因为我使用的是uClibc,它似乎在早期版本中省略了它。这适用于gnu make,但你可以在其他版本中使用类似的东西:

import UIKit

class ViewController: UIViewController {

    var stackView : UIStackView?
    var outerStackView : UIStackView?
    var label1 = UILabel()
    var label2 = UILabel()

    var heightAnchor : NSLayoutConstraint?
    var widthAnchor : NSLayoutConstraint?
    var button : UIButton?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        createStackView()
        createLabelsAndAddToStack()

        button = UIButton(frame: CGRect(x: 20, y: self.view.frame.height - 60, width: self.view.frame.width - 40, height: 40))
        button?.backgroundColor = .green
        button?.setTitleColor(.black, for: .normal)
        button?.setTitle("Toggle Text", for: .normal)
        button?.addTarget(self, action: #selector(toggleText), for: .touchUpInside)
        button?.setTitleColor(.gray, for: .highlighted)
        self.view.addSubview(button!)
    }

    func createStackView(){

        outerStackView = UIStackView(frame: CGRect(x: 20, y: 20, width: self.view.bounds.width - 40, height: 100))
        outerStackView?.axis = .vertical
        outerStackView?.distribution = .fill
        outerStackView?.alignment = .center
        outerStackView?.translatesAutoresizingMaskIntoConstraints = false

        self.view.addSubview(outerStackView!)

        outerStackView?.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 40).isActive = true
        outerStackView?.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -40).isActive = true
        outerStackView?.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 50).isActive = true


        stackView = UIStackView(frame: CGRect(x: 20, y: 20, width: self.view.bounds.width - 40, height: 100))
        stackView?.alignment = .center
        stackView?.spacing = 20
        stackView?.distribution = .fillEqually
        stackView?.axis = .horizontal
        outerStackView?.addArrangedSubview(stackView!)

        heightAnchor = stackView?.heightAnchor.constraint(equalTo: outerStackView!.heightAnchor)
        widthAnchor = stackView?.widthAnchor.constraint(equalTo: outerStackView!.widthAnchor)

    }

    func createLabelsAndAddToStack(){
        label1 = UILabel(frame: .zero)
        label1.textColor = .black
        label1.font = UIFont.systemFont(ofSize: 17)
        label1.text = "Label 1"
        label1.numberOfLines = 0
        stackView?.addArrangedSubview(label1)

        label2 = UILabel(frame: .zero)
        label2.font = UIFont.systemFont(ofSize: 17)
        label2.textColor = .green
        label2.text = "Label 2"
        label2.numberOfLines = 0
        stackView?.addArrangedSubview(label2)

    }

    func adaptStackView(){

        self.outerStackView?.layoutIfNeeded()
        self.stackView?.layoutIfNeeded()
        //let maxWidth = label2.frame.width
        //if you want it to be the max it could be
        let maxWidth = (self.outerStackView!.frame.width - stackView!.spacing)/2
        let height = label2.font.lineHeight

        if let label1Text = label1.text{
            //lets measure
            if label1Text.width(withConstraintedHeight: height, font: label1.font) > maxWidth{
                outerStackView?.axis = .horizontal
                outerStackView?.distribution = .fill

                stackView?.axis = .vertical
                stackView?.distribution = .fill
                stackView?.alignment = .leading

                widthAnchor?.isActive = true
                heightAnchor?.isActive = true

            }else{
                outerStackView?.axis = .vertical
                outerStackView?.distribution = .fill

                stackView?.alignment = .center
                stackView?.axis = .horizontal
                stackView?.distribution = .fillEqually

                stackView?.removeConstraints(self.stackView!.constraints)
                widthAnchor?.isActive = false
                widthAnchor?.isActive = false
            }

            UIView.animate(withDuration: 0.5) {
                self.view.layoutIfNeeded()
            }
        }
    }

    @objc func toggleText(){
        if label1.text == "Label 1"{
            label1.text = "This is some longer text to test everything out to see how we are doing"

        }else{
            label1.text = "Label 1"
        }
        adaptStackView()
    }

}

extension String{
    func width(withConstraintedHeight height: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = self.boundingRect(with: constraintRect, options: [.usesLineFragmentOrigin], attributes: [.font: font], context: nil)

        return ceil(boundingBox.width)
    }
}

答案 4 :(得分:0)

由于预处理器不知道C / C ++语言(它实际上只进行文本替换),我猜这是不可能的。你为什么要这样做?也许还有另一种方式。